Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
MCCCS a0ce32
#include "ext/NotSymmetricExpPotential.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include <tmathutil.h></tmathutil.h>
Toshihiro Shimizu 890ddd
#include <algorithm></algorithm>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
using namespace std;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
namespace {
Toshihiro Shimizu 890ddd
typedef unary_function<double, double=""> unary_functionDD;</double,>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
class mySqr : unary_functionDD {
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  result_type operator()(argument_type x) { return 1.0 - sq(x); }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
class myExp : unary_functionDD {
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  result_type operator()(argument_type x) { return exp(-sq(x)); }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
struct blender {
Shinya Kitaoka 120a6e
  double operator()(double a, double b, double t) {
Shinya Kitaoka 120a6e
    assert(0.0 <= t && t <= 1.0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    return (a * (1.0 - t) + b * t);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
struct blender_2 {
Shinya Kitaoka 120a6e
  double operator()(double a, double b, double t) {
Shinya Kitaoka 120a6e
    assert(0.0 <= t && t <= 1.0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // a(1-t)^2 + 2t*(1-t) + t^2
Shinya Kitaoka 120a6e
    double one_t = 1.0 - t;
Shinya Kitaoka 120a6e
    double num   = 3.0;
Shinya Kitaoka 120a6e
    double den   = 4.0;
Shinya Kitaoka 120a6e
    // solution of a(1-t)^2 + P*2t(1-t) + b*t^2 = (a+b)/2
Shinya Kitaoka 120a6e
    // with t = num/den
Shinya Kitaoka 120a6e
    double middle =
Shinya Kitaoka 120a6e
        sq(den) / (2.0 * num) * ((a + b) * 0.5 - (a + sq(num) * b) / sq(den));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    return a * sq(one_t) + middle * t * one_t + b * sq(t);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
MCCCS a0ce32
void ToonzExt::NotSymmetricExpPotential::setParameters_(const TStroke *ref,
Shinya Kitaoka 120a6e
                                                        double par, double al) {
Shinya Kitaoka 120a6e
  ref_          = ref;
Shinya Kitaoka 120a6e
  par_          = par;
Shinya Kitaoka 120a6e
  actionLength_ = al;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  assert(ref_);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  strokeLength_  = ref->getLength();
MCCCS a0ce32
  lengthAtParam_ = ref->getLength(par);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // lunghezza dal pto di click all'inizio della curva
MCCCS a0ce32
  leftFactor_ = min(lengthAtParam_,
MCCCS a0ce32
                    actionLength_ * 0.5);  // lengthAtParam_ / strokeLength_;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // lunghezza dal pto di click alla fine
MCCCS a0ce32
  rightFactor_ = min(strokeLength_ - lengthAtParam_, actionLength_ * 0.5);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // considero come intervallo di mapping [-range,range].
Shinya Kitaoka 120a6e
  //  4 ha come valore c.a. 10exp-6
Shinya Kitaoka 120a6e
  //  cioƩ sposterei un pixel su un movimento di un milione di pixel
Shinya Kitaoka 120a6e
  range_ = 2.8;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
MCCCS a0ce32
ToonzExt::NotSymmetricExpPotential::~NotSymmetricExpPotential() {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
MCCCS a0ce32
double ToonzExt::NotSymmetricExpPotential::value_(double value2test) const {
Shinya Kitaoka 120a6e
  assert(0.0 <= value2test && value2test <= 1.0);
Shinya Kitaoka 120a6e
  return this->compute_value(value2test);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// normalization of parameter in range interval
MCCCS a0ce32
double ToonzExt::NotSymmetricExpPotential::compute_shape(
Shinya Kitaoka 120a6e
    double value2test) const {
Shinya Kitaoka 120a6e
  double x                       = ref_->getLength(value2test);
Shinya Kitaoka 120a6e
  double shape                   = this->actionLength_ * 0.5;
Shinya Kitaoka 120a6e
  if (isAlmostZero(shape)) shape = 1.0;
MCCCS a0ce32
  x                              = ((x - lengthAtParam_) * range_) / shape;
Shinya Kitaoka 120a6e
  return x;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
MCCCS a0ce32
double ToonzExt::NotSymmetricExpPotential::compute_value(
Shinya Kitaoka 120a6e
    double value2test) const {
Shinya Kitaoka 120a6e
  myExp me;
Shinya Kitaoka 120a6e
  mySqr ms;
Shinya Kitaoka 120a6e
  blender op;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // usually use the form below
Shinya Kitaoka 120a6e
  //     (                ) 2
Shinya Kitaoka 120a6e
  //     ( (x - l)*range_ )
Shinya Kitaoka 120a6e
  //   - (--------------- )
Shinya Kitaoka 120a6e
  //     ( factor         )
Shinya Kitaoka 120a6e
  //            l,r
Shinya Kitaoka 120a6e
  //  e
Shinya Kitaoka 120a6e
  //
Shinya Kitaoka 120a6e
  //  where factor is computed like in constructor
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // on extremes use
Shinya Kitaoka 120a6e
  //     2
Shinya Kitaoka 120a6e
  //  1-x
Shinya Kitaoka 120a6e
  //
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // when is near to extreme uses a mix notation
Shinya Kitaoka 120a6e
  double x   = 0.0;
Shinya Kitaoka 120a6e
  double res = 0.0;
Shinya Kitaoka 120a6e
MCCCS a0ce32
  // length  at parameter
Shinya Kitaoka 120a6e
  x = ref_->getLength(value2test);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  const double tolerance = 2.0;  // need to be pixel based
Shinya Kitaoka 120a6e
  // if is an extreme
MCCCS a0ce32
  if (max(lengthAtParam_, 0.0) < tolerance ||
MCCCS a0ce32
      max(strokeLength_ - lengthAtParam_, 0.0) < tolerance) {
Shinya Kitaoka 120a6e
    double tmp_al = actionLength_ * 0.5;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // compute correct parameter considering offset
Shinya Kitaoka 120a6e
    // try to have a square curve like shape
Shinya Kitaoka 120a6e
    //
Shinya Kitaoka 120a6e
    //       2
Shinya Kitaoka 120a6e
    //  m = x
Shinya Kitaoka 120a6e
    //
Shinya Kitaoka 120a6e
    if (leftFactor_ <= tolerance)
Shinya Kitaoka 120a6e
      x = 1.0 - x / tmp_al;
Shinya Kitaoka 120a6e
    else
Shinya Kitaoka 120a6e
      x = (x - (strokeLength_ - tmp_al)) / tmp_al;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (x < 0.0) return 0.0;
Shinya Kitaoka 120a6e
    assert(0.0 <= x && x <= 1.0 + TConsts::epsilon);
Shinya Kitaoka 120a6e
    res = sq(x);
Shinya Kitaoka 120a6e
  } else  // when is not an extreme
Shinya Kitaoka 120a6e
  {
MCCCS a0ce32
    double length_at_value2test = ref_->getLength(value2test);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    const double min_level = 0.01;
Shinya Kitaoka 120a6e
    // if check a parameter over click point
MCCCS a0ce32
    if (length_at_value2test >= lengthAtParam_) {
Shinya Kitaoka 120a6e
      // check if extreme can be moved from this parameter configuration
Shinya Kitaoka 120a6e
      double tmp_x   = this->compute_shape(1.0);
Shinya Kitaoka 120a6e
      double tmp_res = me(tmp_x);
Shinya Kitaoka 120a6e
      if (tmp_res > min_level) {
Shinya Kitaoka 120a6e
        // please note that in this case
MCCCS a0ce32
        //  lengthAtParam_ + rightFactor_ == strokeLength_
Shinya Kitaoka 120a6e
        // (by ctor).
MCCCS a0ce32
        x = (length_at_value2test - lengthAtParam_) / rightFactor_;
Shinya Kitaoka 120a6e
        assert(0.0 <= x && x <= 1.0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        // then movement use another shape
Shinya Kitaoka 120a6e
        double exp_val = me(x * range_);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        double how_many_of_shape =
MCCCS a0ce32
            (strokeLength_ - lengthAtParam_) / (actionLength_ * 0.5);
Shinya Kitaoka 120a6e
        assert(0.0 <= how_many_of_shape && how_many_of_shape <= 1.0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        // return ms(x);
Shinya Kitaoka 120a6e
        return op(ms(x), exp_val, how_many_of_shape);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    } else {
Shinya Kitaoka 120a6e
      // leftFactor_
Shinya Kitaoka 120a6e
      double tmp_x   = this->compute_shape(0.0);
Shinya Kitaoka 120a6e
      double tmp_res = me(tmp_x);
Shinya Kitaoka 120a6e
      if (tmp_res > min_level) {
MCCCS a0ce32
        double x = length_at_value2test / leftFactor_;
Shinya Kitaoka 120a6e
        assert(0.0 <= x && x <= 1.0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        // then movement use another shape
Shinya Kitaoka 120a6e
        double diff              = x - 1.0;
Shinya Kitaoka 120a6e
        double exp_val           = me(diff * range_);
MCCCS a0ce32
        double how_many_of_shape = lengthAtParam_ / (actionLength_ * 0.5);
Shinya Kitaoka 120a6e
        assert(0.0 <= how_many_of_shape && how_many_of_shape <= 1.0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        // return ms(diff);
Shinya Kitaoka 120a6e
        return op(ms(diff), exp_val, how_many_of_shape);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // default behaviour is an exp
Shinya Kitaoka 120a6e
    x   = this->compute_shape(value2test);
Shinya Kitaoka 120a6e
    res = me(x);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  return res;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
MCCCS a0ce32
ToonzExt::Potential *ToonzExt::NotSymmetricExpPotential::clone() {
MCCCS a0ce32
  return new NotSymmetricExpPotential;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
MCCCS a0ce32
// DEL double  ToonzExt::NotSymmetricExpPotential::gradient(double value2test)
Shinya Kitaoka 120a6e
// const
Shinya Kitaoka 120a6e
// DEL {
Shinya Kitaoka 120a6e
// DEL   assert(false);
Shinya Kitaoka 120a6e
// DEL   //double x = this->compute_shape(value2test);
Shinya Kitaoka 120a6e
// DEL   //double res = -(2.0*range_) / actionLength_ * x * exp(-sq(x));
Shinya Kitaoka 120a6e
// DEL   //return res;
Shinya Kitaoka 120a6e
// DEL   return 0;
Shinya Kitaoka 120a6e
// DEL }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
//  End Of File
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------