#include "ext/NotSimmetricBezierPotential.h" #include "tstroke.h" #include #include #include using namespace std; using namespace std; using namespace ToonzExt; //----------------------------------------------------------------------------- namespace { typedef unary_function unary_functionDD; //--------------------------------------------------------------------------- class myBlendFunc : unary_functionDD { //TCubic c; TQuadratic curve; public: myBlendFunc(double t = 0.0) { curve.setP0(TPointD(0.0, 1.0)); curve.setP1(TPointD(0.5 * (1.0 - t), 1.0)); curve.setP2(TPointD(1.0, 0.0)); } result_type operator()(argument_type x) { result_type out = 0.0; x = fabs(x); if (x >= 1.0) return 0.0; out = curve.getPoint(x).y; return out; } }; } //----------------------------------------------------------------------------- ToonzExt::NotSimmetricBezierPotential::~NotSimmetricBezierPotential() { } //----------------------------------------------------------------------------- void ToonzExt::NotSimmetricBezierPotential::setParameters_(const TStroke *ref, double w, double al) { assert(ref); ref_ = ref; par_ = w; actionLength_ = al; strokeLength_ = ref->getLength(); lenghtAtParam_ = ref->getLength(par_); // lunghezza dal pto di click all'inizio della curva leftFactor_ = min(lenghtAtParam_, actionLength_ * 0.5); //lenghtAtParam_ / strokeLength_; // lunghezza dal pto di click alla fine rightFactor_ = min(strokeLength_ - lenghtAtParam_, actionLength_ * 0.5); } //----------------------------------------------------------------------------- double ToonzExt::NotSimmetricBezierPotential::value_(double value2test) const { assert(0.0 <= value2test && value2test <= 1.0); return this->compute_value(value2test); } //----------------------------------------------------------------------------- // normalization of parameter in range interval double ToonzExt::NotSimmetricBezierPotential::compute_shape(double value2test) const { double x = ref_->getLength(value2test); double shape = this->actionLength_ * 0.5; if (isAlmostZero(shape)) shape = 1.0; x = (x - lenghtAtParam_) / shape; return x; } //----------------------------------------------------------------------------- double ToonzExt::NotSimmetricBezierPotential::compute_value(double value2test) const { myBlendFunc me; // on extremes use // 2 // 1-x // // when is near to extreme uses a mix notation double x = 0.0; double res = 0.0; // lenght at parameter x = ref_->getLength(value2test); const double tolerance = 0.0; // need to be pixel based // if is an extreme if (max(lenghtAtParam_, 0.0) < tolerance || max(strokeLength_ - lenghtAtParam_, 0.0) < tolerance) { double tmp_al = actionLength_ * 0.5; // compute correct parameter considering offset // try to have a square curve like shape // // 2 // m = x // if (leftFactor_ <= tolerance) x = 1.0 - x / tmp_al; else x = (x - (strokeLength_ - tmp_al)) / tmp_al; if (x < 0.0) return 0.0; assert(0.0 <= x && x <= 1.0 + TConsts::epsilon); x = std::min(x, 1.0); // just to avoid problem in production code res = sq(x); } else // when is not an extreme { double lenght_at_value2test = ref_->getLength(value2test); const double min_level = 0.01; // if check a parameter over click point if (lenght_at_value2test >= lenghtAtParam_) { // check if extreme can be moved from this parameter configuration double tmp_x = this->compute_shape(1.0); double tmp_res = me(tmp_x); if (tmp_res > min_level) { // please note that in this case // lenghtAtParam_ + rightFactor_ == strokeLength_ // (by ctor). if (rightFactor_ != 0.0) x = (lenght_at_value2test - lenghtAtParam_) / rightFactor_; else x = 0.0; assert(0.0 - TConsts::epsilon <= x && x <= 1.0 + TConsts::epsilon); if (isAlmostZero(x)) x = 0.0; if (areAlmostEqual(x, 1.0)) x = 1.0; double how_many_of_shape = (strokeLength_ - lenghtAtParam_) / (actionLength_ * 0.5); assert(0.0 <= how_many_of_shape && how_many_of_shape <= 1.0); myBlendFunc bf(how_many_of_shape); return bf(x); } } else { // leftFactor_ double tmp_x = this->compute_shape(0.0); double tmp_res = me(tmp_x); if (tmp_res > min_level) { double x = lenght_at_value2test / leftFactor_; assert(0.0 <= x && x <= 1.0); // then movement use another shape double diff = x - 1.0; double how_many_of_shape = lenghtAtParam_ / (actionLength_ * 0.5); assert(0.0 <= how_many_of_shape && how_many_of_shape <= 1.0); myBlendFunc bf(how_many_of_shape); return bf(diff); } } // default behaviour is an exp x = this->compute_shape(value2test); res = me(x); } return res; } //----------------------------------------------------------------------------- ToonzExt::Potential * ToonzExt::NotSimmetricBezierPotential::clone() { return new NotSimmetricBezierPotential; } //----------------------------------------------------------------------------- // End Of File //-----------------------------------------------------------------------------