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