Toshihiro Shimizu 890ddd
#include "ext/NotSimmetricBezierPotential.h"
Toshihiro Shimizu 890ddd
#include "tstroke.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include <tmathutil.h></tmathutil.h>
Toshihiro Shimizu 890ddd
#include <tcurves.h></tcurves.h>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include <algorithm></algorithm>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
using namespace std;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
using namespace std;
Toshihiro Shimizu 890ddd
using namespace ToonzExt;
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 myBlendFunc : unary_functionDD {
Shinya Kitaoka 120a6e
  // TCubic  c;
Shinya Kitaoka 120a6e
  TQuadratic curve;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  myBlendFunc(double t = 0.0) {
Shinya Kitaoka 120a6e
    curve.setP0(TPointD(0.0, 1.0));
Shinya Kitaoka 120a6e
    curve.setP1(TPointD(0.5 * (1.0 - t), 1.0));
Shinya Kitaoka 120a6e
    curve.setP2(TPointD(1.0, 0.0));
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  result_type operator()(argument_type x) {
Shinya Kitaoka 120a6e
    result_type out = 0.0;
Shinya Kitaoka 120a6e
    x               = fabs(x);
Shinya Kitaoka 120a6e
    if (x >= 1.0) return 0.0;
Shinya Kitaoka 120a6e
    out = curve.getPoint(x).y;
Shinya Kitaoka 120a6e
    return out;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
ToonzExt::NotSimmetricBezierPotential::~NotSimmetricBezierPotential() {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void ToonzExt::NotSimmetricBezierPotential::setParameters_(const TStroke *ref,
Shinya Kitaoka 120a6e
                                                           double w,
Shinya Kitaoka 120a6e
                                                           double al) {
Shinya Kitaoka 120a6e
  assert(ref);
Shinya Kitaoka 120a6e
  ref_          = ref;
Shinya Kitaoka 120a6e
  par_          = w;
Shinya Kitaoka 120a6e
  actionLength_ = al;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  strokeLength_  = ref->getLength();
Shinya Kitaoka 120a6e
  lenghtAtParam_ = ref->getLength(par_);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // lunghezza dal pto di click all'inizio della curva
Shinya Kitaoka 120a6e
  leftFactor_ = min(lenghtAtParam_,
Shinya Kitaoka 120a6e
                    actionLength_ * 0.5);  // lenghtAtParam_ / strokeLength_;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // lunghezza dal pto di click alla fine
Shinya Kitaoka 120a6e
  rightFactor_ = min(strokeLength_ - lenghtAtParam_, actionLength_ * 0.5);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
double ToonzExt::NotSimmetricBezierPotential::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
Shinya Kitaoka 120a6e
double ToonzExt::NotSimmetricBezierPotential::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;
Shinya Kitaoka 120a6e
  x                              = (x - lenghtAtParam_) / shape;
Shinya Kitaoka 120a6e
  return x;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
double ToonzExt::NotSimmetricBezierPotential::compute_value(
Shinya Kitaoka 120a6e
    double value2test) const {
Shinya Kitaoka 120a6e
  myBlendFunc me;
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
Shinya Kitaoka 120a6e
  // lenght  at parameter
Shinya Kitaoka 120a6e
  x = ref_->getLength(value2test);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  const double tolerance = 0.0;  // need to be pixel based
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // if is an extreme
Shinya Kitaoka 120a6e
  if (max(lenghtAtParam_, 0.0) < tolerance ||
Shinya Kitaoka 120a6e
      max(strokeLength_ - lenghtAtParam_, 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
    x   = std::min(x, 1.0);  // just to avoid problem in production code
Shinya Kitaoka 120a6e
    res = sq(x);
Shinya Kitaoka 120a6e
  } else  // when is not an extreme
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    double lenght_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
Shinya Kitaoka 120a6e
    if (lenght_at_value2test >= lenghtAtParam_) {
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
Shinya Kitaoka 120a6e
        //  lenghtAtParam_ + rightFactor_ == strokeLength_
Shinya Kitaoka 120a6e
        // (by ctor).
Shinya Kitaoka 120a6e
        if (rightFactor_ != 0.0)
Shinya Kitaoka 120a6e
          x = (lenght_at_value2test - lenghtAtParam_) / rightFactor_;
Shinya Kitaoka 120a6e
        else
Shinya Kitaoka 120a6e
          x = 0.0;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        assert(0.0 - TConsts::epsilon <= x && x <= 1.0 + TConsts::epsilon);
Shinya Kitaoka 120a6e
        if (isAlmostZero(x)) x = 0.0;
Shinya Kitaoka 120a6e
        if (areAlmostEqual(x, 1.0)) x = 1.0;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        double how_many_of_shape =
Shinya Kitaoka 120a6e
            (strokeLength_ - lenghtAtParam_) / (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
        myBlendFunc bf(how_many_of_shape);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        return bf(x);
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) {
Shinya Kitaoka 120a6e
        double x = lenght_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
Shinya Kitaoka 120a6e
        double how_many_of_shape = lenghtAtParam_ / (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
        myBlendFunc bf(how_many_of_shape);
Shinya Kitaoka 120a6e
        return bf(diff);
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
Shinya Kitaoka 120a6e
ToonzExt::Potential *ToonzExt::NotSimmetricBezierPotential::clone() {
Shinya Kitaoka 120a6e
  return new NotSimmetricBezierPotential;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
//  End Of File
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------