MCCCS a0ce32
#include "ext/NotSymmetricBezierPotential.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
MCCCS a0ce32
ToonzExt::NotSymmetricBezierPotential::~NotSymmetricBezierPotential() {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
MCCCS a0ce32
void ToonzExt::NotSymmetricBezierPotential::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();
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);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
MCCCS a0ce32
double ToonzExt::NotSymmetricBezierPotential::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::NotSymmetricBezierPotential::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_) / shape;
Shinya Kitaoka 120a6e
  return x;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
MCCCS a0ce32
double ToonzExt::NotSymmetricBezierPotential::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
MCCCS a0ce32
  // length  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
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
    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
  {
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).
Shinya Kitaoka 120a6e
        if (rightFactor_ != 0.0)
MCCCS a0ce32
          x = (length_at_value2test - lengthAtParam_) / 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 =
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
        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) {
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
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
        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
MCCCS a0ce32
ToonzExt::Potential *ToonzExt::NotSymmetricBezierPotential::clone() {
MCCCS a0ce32
  return new NotSymmetricBezierPotential;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
//  End Of File
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------