Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/**
Toshihiro Shimizu 890ddd
 * @author  Fabrizio Morciano <fabrizio.morciano@gmail.com></fabrizio.morciano@gmail.com>
Toshihiro Shimizu 890ddd
 */
Toshihiro Shimizu 890ddd
#ifdef _DEBUG
Toshihiro Shimizu 890ddd
#define _STLP_DEBUG 1
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "ext/StrokeDeformationImpl.h"
Toshihiro Shimizu 890ddd
#include "ext/StrokeDeformation.h"
Toshihiro Shimizu 890ddd
#include "ext/SquarePotential.h"
Toshihiro Shimizu 890ddd
#include "ext/StrokeParametricDeformer.h"
Toshihiro Shimizu 890ddd
//#include "ext/NotSimmetricBezierPotential.h"
Toshihiro Shimizu 890ddd
#include "ext/ContextStatus.h"
Toshihiro Shimizu 890ddd
#include "ext/Designer.h"
Toshihiro Shimizu 890ddd
//#include "ext/TriParam.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include <tcurves.h></tcurves.h>
Toshihiro Shimizu 890ddd
#include <tstrokeutil.h></tstrokeutil.h>
Toshihiro Shimizu 890ddd
//#include <tvectorimage.h></tvectorimage.h>
Toshihiro Shimizu 890ddd
#include <tmathutil.h></tmathutil.h>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include <algorithm></algorithm>
Toshihiro Shimizu 890ddd
#include <iterator></iterator>
Toshihiro Shimizu 890ddd
#include <vector></vector>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "DeformationSelector.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
using namespace ToonzExt;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
namespace
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*
Toshihiro Shimizu 890ddd
   * Avoid to reduce curves with great zoom out.
Toshihiro Shimizu 890ddd
   * assert that pixelSize and factor > 0.0
Toshihiro Shimizu 890ddd
   */
Toshihiro Shimizu 890ddd
double
Toshihiro Shimizu 890ddd
computeReductionFactor(double pixelSize,
Toshihiro Shimizu 890ddd
					   double factor)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	assert(pixelSize > 0.0 &&
Toshihiro Shimizu 890ddd
		   factor > 0.0);
Toshihiro Shimizu 890ddd
	if (factor <= 0.0)
Toshihiro Shimizu 890ddd
		factor = 1.0;
Toshihiro Shimizu 890ddd
	if (pixelSize <= 0.0 ||
Toshihiro Shimizu 890ddd
		pixelSize > 1.0)
Toshihiro Shimizu 890ddd
		pixelSize = 1.0;
Toshihiro Shimizu 890ddd
	return pixelSize * factor;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
double
Toshihiro Shimizu 890ddd
retrieveParamAtLengthWithOffset(const TStroke *stroke2change,
Toshihiro Shimizu 890ddd
								double length, // = 0.5 * strokeLength,
Toshihiro Shimizu 890ddd
								double offset)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (!isValid(stroke2change) ||
Toshihiro Shimizu 890ddd
		!isValid(offset) ||
Toshihiro Shimizu 890ddd
		length < 0)
Toshihiro Shimizu 890ddd
		return -1;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double
Toshihiro Shimizu 890ddd
		strokeLength = stroke2change->getLength();
Toshihiro Shimizu 890ddd
	assert(strokeLength >= 0.0 &&
Toshihiro Shimizu 890ddd
		   "Not valid length");
Toshihiro Shimizu 890ddd
	if (strokeLength < 0) {
Toshihiro Shimizu 890ddd
		return -1;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double
Toshihiro Shimizu 890ddd
		lengthAtW = stroke2change->getLength(offset);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	assert(strokeLength >= lengthAtW &&
Toshihiro Shimizu 890ddd
		   "Position of parameter is greater than stroke length!!!");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (strokeLength < lengthAtW)
Toshihiro Shimizu 890ddd
		return -1;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double
Toshihiro Shimizu 890ddd
		newLength = -1;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (stroke2change->isSelfLoop()) {
Toshihiro Shimizu 890ddd
		if (length >= 0)
Toshihiro Shimizu 890ddd
			newLength = length > lengthAtW ? length + lengthAtW : lengthAtW - length;
Toshihiro Shimizu 890ddd
	} else
Toshihiro Shimizu 890ddd
		newLength = std::min(length + lengthAtW,
Toshihiro Shimizu 890ddd
							 strokeLength);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return stroke2change->getParameterAtLength(newLength);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool rotateStroke(const TStroke *stroke2change,
Toshihiro Shimizu 890ddd
				  TStroke *&rotated,
Toshihiro Shimizu 890ddd
				  double &from,
Toshihiro Shimizu 890ddd
				  double &to,
Toshihiro Shimizu 890ddd
				  TPointD &old_w0_pos)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (!stroke2change ||
Toshihiro Shimizu 890ddd
		!isValid(from) ||
Toshihiro Shimizu 890ddd
		!isValid(to))
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	rotated = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// save position of w=0 (useful to retrieve this
Toshihiro Shimizu 890ddd
	//  position after changes)
Toshihiro Shimizu 890ddd
	old_w0_pos = convert(stroke2change->getControlPoint(0));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double
Toshihiro Shimizu 890ddd
		rotateAtLength = stroke2change->getLength(to);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	assert(rotateAtLength >= 0.0);
Toshihiro Shimizu 890ddd
	if (rotateAtLength < 0)
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//TStroke*
Toshihiro Shimizu 890ddd
	rotated = ToonzExt::rotateControlPoint(stroke2change,
Toshihiro Shimizu 890ddd
										   ToonzExt::EvenInt(0),
Toshihiro Shimizu 890ddd
										   rotateAtLength);
Toshihiro Shimizu 890ddd
	if (!rotated)
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	from = rotated->getW(stroke2change->getPoint(from));
Toshihiro Shimizu 890ddd
	to = rotated->getW(stroke2change->getPoint(to));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// save some other information (style, etc..)
Toshihiro Shimizu 890ddd
	ToonzExt::cloneStrokeStatus(stroke2change,
Toshihiro Shimizu 890ddd
								rotated);
Toshihiro Shimizu 890ddd
	return true; //rotated;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TStroke *
Toshihiro Shimizu 890ddd
rotateControlPointAtPoint(const TStroke *stroke,
Toshihiro Shimizu 890ddd
						  const TPointD &pnt)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (!stroke ||
Toshihiro Shimizu 890ddd
		tdistance2(stroke->getPoint(0.0),
Toshihiro Shimizu 890ddd
				   pnt) < sq(TConsts::epsilon))
Toshihiro Shimizu 890ddd
		return 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double
Toshihiro Shimizu 890ddd
		w = stroke->getW(pnt);
Toshihiro Shimizu 890ddd
	TPointD
Toshihiro Shimizu 890ddd
		theSamePnt = stroke->getPoint(w);
Toshihiro Shimizu 890ddd
	double
Toshihiro Shimizu 890ddd
		length = stroke->getLength(w);
Toshihiro Shimizu 890ddd
	return ToonzExt::rotateControlPoint(stroke,
Toshihiro Shimizu 890ddd
										ToonzExt::EvenInt(0),
Toshihiro Shimizu 890ddd
										length);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool findExtremesFromActionLength(double toolActionLength,
Toshihiro Shimizu 890ddd
								  const TStroke *stroke,
Toshihiro Shimizu 890ddd
								  double w,
Toshihiro Shimizu 890ddd
								  ToonzExt::Interval &out)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	out = ToonzExt::Interval(-1.0, -1.0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!stroke ||
Toshihiro Shimizu 890ddd
		0.0 > w ||
Toshihiro Shimizu 890ddd
		w > 1.0)
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double
Toshihiro Shimizu 890ddd
		emiToolSize = 0.5 * toolActionLength;
Toshihiro Shimizu 890ddd
	double
Toshihiro Shimizu 890ddd
		strokelength = stroke->getLength();
Toshihiro Shimizu 890ddd
	double
Toshihiro Shimizu 890ddd
		lengthAtParam = stroke->getLength(w);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	assert(emiToolSize >= 0.0 &&
Toshihiro Shimizu 890ddd
		   strokelength >= 0.0 &&
Toshihiro Shimizu 890ddd
		   lengthAtParam >= 0.0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (emiToolSize > strokelength * 0.5) {
Toshihiro Shimizu 890ddd
		if (stroke->isSelfLoop()) {
Toshihiro Shimizu 890ddd
			emiToolSize = strokelength * 0.5;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			// first and second are the same
Toshihiro Shimizu 890ddd
			lengthAtParam += emiToolSize;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			if (lengthAtParam > strokelength)
Toshihiro Shimizu 890ddd
				lengthAtParam -= strokelength;
Toshihiro Shimizu 890ddd
			out.first =
Toshihiro Shimizu 890ddd
				out.second = stroke->getParameterAtLength(lengthAtParam);
Toshihiro Shimizu 890ddd
		} else {
Toshihiro Shimizu 890ddd
			out.first = 0.0;
Toshihiro Shimizu 890ddd
			out.second = 1.0;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		return true;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (emiToolSize < 0.0 ||
Toshihiro Shimizu 890ddd
		strokelength < 0.0 ||
Toshihiro Shimizu 890ddd
		lengthAtParam < 0.0)
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// [out] now is length, range 0,length
Toshihiro Shimizu 890ddd
	out.first = lengthAtParam - emiToolSize;
Toshihiro Shimizu 890ddd
	out.second = lengthAtParam + emiToolSize;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (stroke->isSelfLoop()) {
Toshihiro Shimizu 890ddd
		if (out.first < 0.0) {
Toshihiro Shimizu 890ddd
			out.first = strokelength + out.first;
Toshihiro Shimizu 890ddd
			assert(out.first < strokelength);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (out.second > strokelength) {
Toshihiro Shimizu 890ddd
			out.second = out.second - strokelength;
Toshihiro Shimizu 890ddd
			assert(0.0 < out.second &&
Toshihiro Shimizu 890ddd
				   out.second < strokelength);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	} else {
Toshihiro Shimizu 890ddd
		out.first = std::max(out.first, 0.0);
Toshihiro Shimizu 890ddd
		out.second = std::min(out.second, strokelength);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// [out] now is parameter, range 0,1
Toshihiro Shimizu 890ddd
	out.first = stroke->getParameterAtLength(out.first);
Toshihiro Shimizu 890ddd
	out.second = stroke->getParameterAtLength(out.second);
Toshihiro Shimizu 890ddd
#ifdef _DEBUG
Toshihiro Shimizu 890ddd
	if (!stroke->isSelfLoop())
Toshihiro Shimizu 890ddd
		assert(out.first <= out.second);
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
	return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool areDifferent(const TStroke *ref1,
Toshihiro Shimizu 890ddd
				  const TStroke *ref2)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (!isValid(ref1) ||
Toshihiro Shimizu 890ddd
		!isValid(ref2))
Toshihiro Shimizu 890ddd
		return true;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int cpCount1 = ref1->getControlPointCount();
Toshihiro Shimizu 890ddd
	int cpCount2 = ref2->getControlPointCount();
Toshihiro Shimizu 890ddd
	if (cpCount1 != cpCount2)
Toshihiro Shimizu 890ddd
		return true;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	while (--cpCount1 >= 0) {
Toshihiro Shimizu 890ddd
		if (ref1->getControlPoint(cpCount1) !=
Toshihiro Shimizu 890ddd
			ref2->getControlPoint(cpCount1))
Toshihiro Shimizu 890ddd
			return true;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	assert(cpCount1 == -1);
Toshihiro Shimizu 890ddd
	return false;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TStroke *
Toshihiro Shimizu 890ddd
	StrokeDeformationImpl::copyOfLastSelectedStroke_ = 0; // deep copy stroke selected previously
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
const ContextStatus *&
Toshihiro Shimizu 890ddd
StrokeDeformationImpl::getImplStatus()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	// if multi threading this datas need to be serialized
Toshihiro Shimizu 890ddd
	// a ref to status
Toshihiro Shimizu 890ddd
	static const ContextStatus *contextStatus_instance;
Toshihiro Shimizu 890ddd
	return contextStatus_instance;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TStroke *&
Toshihiro Shimizu 890ddd
StrokeDeformationImpl::getLastSelectedStroke()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	static TStroke *lastSelectedStroke_instance;
Toshihiro Shimizu 890ddd
	return lastSelectedStroke_instance;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void StrokeDeformationImpl::setLastSelectedStroke(TStroke *stroke)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TStroke *&lastSelStroke = getLastSelectedStroke();
Toshihiro Shimizu 890ddd
	lastSelStroke = stroke;
Toshihiro Shimizu 890ddd
	if (lastSelStroke) {
Toshihiro Shimizu 890ddd
		delete copyOfLastSelectedStroke_;
Toshihiro Shimizu 890ddd
		copyOfLastSelectedStroke_ = new TStroke(*lastSelStroke);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
int &StrokeDeformationImpl::getLastSelectedDegree()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	static int lastSelectedDegree_instance;
Toshihiro Shimizu 890ddd
	return lastSelectedDegree_instance;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void StrokeDeformationImpl::setLastSelectedDegree(int degree)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	getLastSelectedDegree() = degree;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
ToonzExt::Intervals &
Toshihiro Shimizu 890ddd
StrokeDeformationImpl::getSpiresList()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	static ToonzExt::Intervals listOfSpire_instance;
Toshihiro Shimizu 890ddd
	return listOfSpire_instance;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
ToonzExt::Intervals &
Toshihiro Shimizu 890ddd
StrokeDeformationImpl::getStraightsList()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	static ToonzExt::Intervals listOfStraight_instance;
Toshihiro Shimizu 890ddd
	return listOfStraight_instance;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
StrokeDeformationImpl::StrokeDeformationImpl()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	shortcutKey_ = ContextStatus::NONE;
Toshihiro Shimizu 890ddd
	cursorId_ = -1;
Toshihiro Shimizu 890ddd
	this->reset();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
StrokeDeformationImpl::~StrokeDeformationImpl()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	clearPointerContainer(strokes_);
Toshihiro Shimizu 890ddd
	delete potential_;
Toshihiro Shimizu 890ddd
	potential_ = 0;
Toshihiro Shimizu 890ddd
	delete deformer_;
Toshihiro Shimizu 890ddd
	deformer_ = 0;
Toshihiro Shimizu 890ddd
	delete copyOfLastSelectedStroke_;
Toshihiro Shimizu 890ddd
	copyOfLastSelectedStroke_ = 0;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool StrokeDeformationImpl::activate_impl(const ContextStatus *status)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	assert(status && "Not status available");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!status ||
Toshihiro Shimizu 890ddd
		!this->init(status))
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double
Toshihiro Shimizu 890ddd
		w = status->w_;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	ToonzExt::Interval
Toshihiro Shimizu 890ddd
		extremes = this->getExtremes();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TStroke *
Toshihiro Shimizu 890ddd
		stroke2transform;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!this->computeStroke2Transform(status,
Toshihiro Shimizu 890ddd
									   stroke2transform,
Toshihiro Shimizu 890ddd
									   w,
Toshihiro Shimizu 890ddd
									   extremes))
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// to avoid strange behaviour in limit's value
Toshihiro Shimizu 890ddd
	if (areAlmostEqual(extremes.first, w))
Toshihiro Shimizu 890ddd
		w = extremes.first;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (areAlmostEqual(extremes.second, w))
Toshihiro Shimizu 890ddd
		w = extremes.second;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	assert(extremes.first <= w &&
Toshihiro Shimizu 890ddd
		   w <= extremes.second);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (extremes.first > w ||
Toshihiro Shimizu 890ddd
		w > extremes.second) {
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	vector<double></double>
Toshihiro Shimizu 890ddd
		splitParameter;
Toshihiro Shimizu 890ddd
	splitParameter.push_back(extremes.first);
Toshihiro Shimizu 890ddd
	splitParameter.push_back(extremes.second);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	assert(strokes_.empty());
Toshihiro Shimizu 890ddd
	if (!strokes_.empty())
Toshihiro Shimizu 890ddd
		clearPointerContainer(strokes_);
Toshihiro Shimizu 890ddd
	splitStroke(*stroke2transform,
Toshihiro Shimizu 890ddd
				splitParameter,
Toshihiro Shimizu 890ddd
				strokes_);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	assert(strokes_.size() == 3);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// I don't know how to manage properly this case
Toshihiro Shimizu 890ddd
	if (strokes_.size() != 3) {
Toshihiro Shimizu 890ddd
		clearPointerContainer(strokes_);
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// stroke to change
Toshihiro Shimizu 890ddd
	stroke2manipulate_ = strokes_[1];
Toshihiro Shimizu 890ddd
	assert(stroke2manipulate_ && " Not valid reference to stroke to move!!!");
Toshihiro Shimizu 890ddd
	if (!stroke2manipulate_)
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// remove empty stroke
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		TStroke *tmp_stroke = strokes_[2];
Toshihiro Shimizu 890ddd
		if (isAlmostZero(tmp_stroke->getLength())) {
Toshihiro Shimizu 890ddd
			std::vector<tstroke *="">::iterator</tstroke>
Toshihiro Shimizu 890ddd
				it = strokes_.begin();
Toshihiro Shimizu 890ddd
			std::advance(it, 2);
Toshihiro Shimizu 890ddd
			strokes_.erase(it);
Toshihiro Shimizu 890ddd
			delete tmp_stroke;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		tmp_stroke = strokes_[0];
Toshihiro Shimizu 890ddd
		if (isAlmostZero(tmp_stroke->getLength())) {
Toshihiro Shimizu 890ddd
			strokes_.erase(strokes_.begin());
Toshihiro Shimizu 890ddd
			delete tmp_stroke;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		// little movement of control points to have not empty
Toshihiro Shimizu 890ddd
		//  length
Toshihiro Shimizu 890ddd
		if (isAlmostZero(stroke2manipulate_->getLength())) {
Toshihiro Shimizu 890ddd
			int
Toshihiro Shimizu 890ddd
				count = stroke2manipulate_->getControlPointCount() - 1;
Toshihiro Shimizu 890ddd
			assert(count > 0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			TThickPoint
Toshihiro Shimizu 890ddd
				pnt0 = stroke2manipulate_->getControlPoint(0),
Toshihiro Shimizu 890ddd
				pntn = stroke2manipulate_->getControlPoint(count),
Toshihiro Shimizu 890ddd
				delta = TThickPoint(2.0 * TConsts::epsilon,
Toshihiro Shimizu 890ddd
									-2.0 * TConsts::epsilon,
Toshihiro Shimizu 890ddd
									0.0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			stroke2manipulate_->setControlPoint(0, pnt0 - delta);
Toshihiro Shimizu 890ddd
			stroke2manipulate_->setControlPoint(count, pntn + delta);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// simple check for empty chunk
Toshihiro Shimizu 890ddd
	int
Toshihiro Shimizu 890ddd
		cp_count = stroke2manipulate_->getChunkCount();
Toshihiro Shimizu 890ddd
	const TThickQuadratic
Toshihiro Shimizu 890ddd
		*tq;
Toshihiro Shimizu 890ddd
	bool
Toshihiro Shimizu 890ddd
		haveEmpty = false;
Toshihiro Shimizu 890ddd
	while (--cp_count >= 0) {
Toshihiro Shimizu 890ddd
		tq = stroke2manipulate_->getChunk(cp_count);
Toshihiro Shimizu 890ddd
		//    assert( tq->getLength() != 0.0 );
Toshihiro Shimizu 890ddd
		if (tq->getLength() == 0.0)
Toshihiro Shimizu 890ddd
			haveEmpty = true;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (haveEmpty) {
Toshihiro Shimizu 890ddd
		const double
Toshihiro Shimizu 890ddd
			reductionFactor = computeReductionFactor(getImplStatus()->pixelSize_,
Toshihiro Shimizu 890ddd
													 1.0);
Toshihiro Shimizu 890ddd
		stroke2manipulate_->reduceControlPoints(reductionFactor);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TPointD
Toshihiro Shimizu 890ddd
		pntOnStroke = stroke2transform->getPoint(w);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// parameter need to be recomputed to match
Toshihiro Shimizu 890ddd
	// with new stroke
Toshihiro Shimizu 890ddd
	w = stroke2manipulate_->getW(pntOnStroke);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//  prevStyle_ = stroke2transform->getStyle();
Toshihiro Shimizu 890ddd
	//  set a style for error
Toshihiro Shimizu 890ddd
	//  stroke2manipulate_->setStyle( 4 );
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// in this deformer all stroke need to be moved
Toshihiro Shimizu 890ddd
	double lengthOfAction = this->findActionLength();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool
Toshihiro Shimizu 890ddd
		exception = false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	try {
Toshihiro Shimizu 890ddd
		// create a new stroke deformer
Toshihiro Shimizu 890ddd
		delete deformer_;
Toshihiro Shimizu 890ddd
		deformer_ = new StrokeParametricDeformer(lengthOfAction,
Toshihiro Shimizu 890ddd
												 w,
Toshihiro Shimizu 890ddd
												 stroke2manipulate_,
Toshihiro Shimizu 890ddd
												 potential_->clone());
Toshihiro Shimizu 890ddd
	} catch (std::invalid_argument &) {
Toshihiro Shimizu 890ddd
		exception = true;
Toshihiro Shimizu 890ddd
		assert(!"Invalid argument");
Toshihiro Shimizu 890ddd
	} catch (...) {
Toshihiro Shimizu 890ddd
		exception = true;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	assert(deformer_ &&
Toshihiro Shimizu 890ddd
		   "Deformer is not available");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (exception) {
Toshihiro Shimizu 890ddd
		deformer_ = 0;
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	assert(getImplStatus() != 0 && "ContextStatus is null???");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!getImplStatus()) {
Toshihiro Shimizu 890ddd
		delete deformer_;
Toshihiro Shimizu 890ddd
		this->reset();
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	// change the threshold value of increser,
Toshihiro Shimizu 890ddd
	//  if value is greater than diff add control points
Toshihiro Shimizu 890ddd
	deformer_->setDiff(getImplStatus()->deformerSensibility_);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// just to be sure to have a control point where
Toshihiro Shimizu 890ddd
	// stroke is selected
Toshihiro Shimizu 890ddd
	stroke2manipulate_->insertControlPoints(w);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//  two different case:
Toshihiro Shimizu 890ddd
	//  (1) point at w=0 is not in stroke to transform
Toshihiro Shimizu 890ddd
	//  (2) point at w=0 is in stroke to transform
Toshihiro Shimizu 890ddd
	//  in case (2) it is mandatory to retrieve the
Toshihiro Shimizu 890ddd
	//  parameter where stroke2transform is equal to
Toshihiro Shimizu 890ddd
	//  w=0 and store it.
Toshihiro Shimizu 890ddd
	//  old_w0_pos_ will be used in deactivate method
Toshihiro Shimizu 890ddd
	if (old_w0_pos_ != TConsts::napd) {
Toshihiro Shimizu 890ddd
		double
Toshihiro Shimizu 890ddd
			w = stroke2manipulate_->getW(old_w0_pos_);
Toshihiro Shimizu 890ddd
		TPointD
Toshihiro Shimizu 890ddd
			pnt = stroke2manipulate_->getPoint(w);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (tdistance2(pnt, old_w0_pos_) < sq(TConsts::epsilon)) {
Toshihiro Shimizu 890ddd
			// the this position can be modifyed during drag
Toshihiro Shimizu 890ddd
			old_w0_ = w;
Toshihiro Shimizu 890ddd
		} else
Toshihiro Shimizu 890ddd
			old_w0_ = -1;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool
Toshihiro Shimizu 890ddd
		test = increaseControlPoints(*stroke2manipulate_,
Toshihiro Shimizu 890ddd
									 *deformer_,
Toshihiro Shimizu 890ddd
									 getImplStatus()->pixelSize_);
Toshihiro Shimizu 890ddd
	/*
Toshihiro Shimizu 890ddd
    // New Increaser behaviour
Toshihiro Shimizu 890ddd
    deformer_->setMouseMove(0,100);
Toshihiro Shimizu 890ddd
    extremes_ = Toonz::increase_cp (stroke2manipulate_, 
Toshihiro Shimizu 890ddd
    deformer_);
Toshihiro Shimizu 890ddd
  //*/
Toshihiro Shimizu 890ddd
	if (!test)
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	stroke2manipulate_->disableComputeOfCaches();
Toshihiro Shimizu 890ddd
	return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void StrokeDeformationImpl::update_impl(const TPointD &delta)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	assert(stroke2manipulate_ &&
Toshihiro Shimizu 890ddd
		   deformer_ &&
Toshihiro Shimizu 890ddd
		   "Stroke and Deformer are available");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!stroke2manipulate_ ||
Toshihiro Shimizu 890ddd
		!deformer_)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// update delta in deformer
Toshihiro Shimizu 890ddd
	deformer_->setMouseMove(delta.x, delta.y);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	modifyControlPoints(*stroke2manipulate_,
Toshihiro Shimizu 890ddd
						*deformer_);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TStroke *
Toshihiro Shimizu 890ddd
StrokeDeformationImpl::deactivate_impl()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (!stroke2manipulate_ ||
Toshihiro Shimizu 890ddd
		!getImplStatus()) {
Toshihiro Shimizu 890ddd
		this->reset();
Toshihiro Shimizu 890ddd
		return 0;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// retrieve the point
Toshihiro Shimizu 890ddd
	if (old_w0_ != -1)
Toshihiro Shimizu 890ddd
		old_w0_pos_ = stroke2manipulate_->getPoint(old_w0_);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	const double
Toshihiro Shimizu 890ddd
		reductionFactor = computeReductionFactor(getImplStatus()->pixelSize_,
Toshihiro Shimizu 890ddd
												 3.0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//stroke2manipulate_->enableComputeOfCaches ();
Toshihiro Shimizu 890ddd
	//stroke2manipulate_->reduceControlPoints (reductionFactor);
Toshihiro Shimizu 890ddd
	const int
Toshihiro Shimizu 890ddd
		size = stroke2manipulate_->getControlPointCount();
Toshihiro Shimizu 890ddd
	vector<tthickpoint></tthickpoint>
Toshihiro Shimizu 890ddd
		pnt(size);
Toshihiro Shimizu 890ddd
	for (int i = 0;
Toshihiro Shimizu 890ddd
		 i < size;
Toshihiro Shimizu 890ddd
		 ++i)
Toshihiro Shimizu 890ddd
		pnt[i] = stroke2manipulate_->getControlPoint(i);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	std::vector<tstroke *="">::iterator</tstroke>
Toshihiro Shimizu 890ddd
		it = std::find(strokes_.begin(),
Toshihiro Shimizu 890ddd
					   strokes_.end(),
Toshihiro Shimizu 890ddd
					   stroke2manipulate_);
Toshihiro Shimizu 890ddd
	assert(it != strokes_.end());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int pos = std::distance(strokes_.begin(),
Toshihiro Shimizu 890ddd
							it);
Toshihiro Shimizu 890ddd
	stroke2manipulate_ = 0;
Toshihiro Shimizu 890ddd
	delete strokes_[pos];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TStroke *tmpStroke = new TStroke(pnt);
Toshihiro Shimizu 890ddd
	assert((tmpStroke != 0) && "Not valid stroke!");
Toshihiro Shimizu 890ddd
	strokes_[pos] = tmpStroke;
Toshihiro Shimizu 890ddd
	strokes_[pos]->reduceControlPoints(reductionFactor);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//strokes_[pos] = TStroke::interpolate(pnt,
Toshihiro Shimizu 890ddd
	//                                   reductionFactor,
Toshihiro Shimizu 890ddd
	//                                   false);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TStroke
Toshihiro Shimizu 890ddd
		*ref = Toonz::merge(strokes_);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	ToonzExt::cloneStrokeStatus(getImplStatus()->stroke2change_,
Toshihiro Shimizu 890ddd
								ref);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (old_w0_pos_ != TConsts::napd) {
Toshihiro Shimizu 890ddd
		// restore (if necessary) the initial position of
Toshihiro Shimizu 890ddd
		// a stroke
Toshihiro Shimizu 890ddd
		TStroke *
Toshihiro Shimizu 890ddd
			rotated = rotateControlPointAtPoint(ref,
Toshihiro Shimizu 890ddd
												old_w0_pos_);
Toshihiro Shimizu 890ddd
		if (rotated) {
Toshihiro Shimizu 890ddd
			delete ref;
Toshihiro Shimizu 890ddd
			ref = rotated;
Toshihiro Shimizu 890ddd
			if (getImplStatus())
Toshihiro Shimizu 890ddd
				ToonzExt::cloneStrokeStatus(getImplStatus()->stroke2change_,
Toshihiro Shimizu 890ddd
											ref);
Toshihiro Shimizu 890ddd
			else {
Toshihiro Shimizu 890ddd
				delete ref;
Toshihiro Shimizu 890ddd
				ref = 0;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	this->reset();
Toshihiro Shimizu 890ddd
	return ref;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void StrokeDeformationImpl::reset()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	old_w0_ = -1;
Toshihiro Shimizu 890ddd
	old_w0_pos_ = TConsts::napd;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	deformer_ = 0;
Toshihiro Shimizu 890ddd
	getImplStatus() = 0;
Toshihiro Shimizu 890ddd
	this->setLastSelectedDegree(-1);
Toshihiro Shimizu 890ddd
	this->setLastSelectedStroke(0);
Toshihiro Shimizu 890ddd
	this->getSpiresList().clear();
Toshihiro Shimizu 890ddd
	this->getStraightsList().clear();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	stroke2manipulate_ = 0;
Toshihiro Shimizu 890ddd
	clearPointerContainer(strokes_); // stroke2move is deleted here (it
Toshihiro Shimizu 890ddd
									 // is in vector)
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TStroke *
Toshihiro Shimizu 890ddd
StrokeDeformationImpl::getTransformedStroke()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return this->stroke2manipulate_;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
ToonzExt::Potential *
Toshihiro Shimizu 890ddd
StrokeDeformationImpl::getPotential()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return this->potential_;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void StrokeDeformationImpl::draw(Designer *designer)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void StrokeDeformationImpl::setPotential(Potential *potential)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	assert(potential);
Toshihiro Shimizu 890ddd
	potential_ = potential;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool StrokeDeformationImpl::check(const ContextStatus *status)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (!status ||
Toshihiro Shimizu 890ddd
		!this->init(status))
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return this->check_(status);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TPointD &
Toshihiro Shimizu 890ddd
StrokeDeformationImpl::oldW0()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return old_w0_pos_;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
ToonzExt::Interval
Toshihiro Shimizu 890ddd
StrokeDeformationImpl::getExtremes()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	ToonzExt::Interval
Toshihiro Shimizu 890ddd
		extremes = ToonzExt::Interval(-1.0, -1.0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!getImplStatus())
Toshihiro Shimizu 890ddd
		return extremes;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// if it is manual
Toshihiro Shimizu 890ddd
	if (getImplStatus()->isManual_ == true) {
Toshihiro Shimizu 890ddd
		findExtremesFromActionLength(getImplStatus()->lengthOfAction_,
Toshihiro Shimizu 890ddd
									 getImplStatus()->stroke2change_,
Toshihiro Shimizu 890ddd
									 getImplStatus()->w_,
Toshihiro Shimizu 890ddd
									 extremes);
Toshihiro Shimizu 890ddd
	} else {
Toshihiro Shimizu 890ddd
		// if there are some special key down all will be managed in deformation
Toshihiro Shimizu 890ddd
		this->findExtremes_(getImplStatus(),
Toshihiro Shimizu 890ddd
							extremes);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return extremes;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool StrokeDeformationImpl::init(const ContextStatus *status)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (!status ||
Toshihiro Shimizu 890ddd
		!isValid(status->stroke2change_) ||
Toshihiro Shimizu 890ddd
		!isValid(status->w_)) {
Toshihiro Shimizu 890ddd
		this->reset();
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	getImplStatus() = status;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!this->getLastSelectedStroke() ||
Toshihiro Shimizu 890ddd
		this->getLastSelectedStroke() != status->stroke2change_ ||
Toshihiro Shimizu 890ddd
		areDifferent(copyOfLastSelectedStroke_,
Toshihiro Shimizu 890ddd
					 status->stroke2change_) ||
Toshihiro Shimizu 890ddd
		(this->getLastSelectedDegree() == -1) ||
Toshihiro Shimizu 890ddd
		(this->getLastSelectedDegree() != status->cornerSize_)) {
Toshihiro Shimizu 890ddd
		this->getSpiresList().clear();
Toshihiro Shimizu 890ddd
		this->getStraightsList().clear();
Toshihiro Shimizu 890ddd
		// recompute cache
Toshihiro Shimizu 890ddd
		ToonzExt::findCorners(status->stroke2change_,
Toshihiro Shimizu 890ddd
							  this->getSpiresList(),
Toshihiro Shimizu 890ddd
							  this->getStraightsList(),
Toshihiro Shimizu 890ddd
							  status->cornerSize_,
Toshihiro Shimizu 890ddd
							  TConsts::epsilon);
Toshihiro Shimizu 890ddd
		this->setLastSelectedStroke(status->stroke2change_);
Toshihiro Shimizu 890ddd
		this->setLastSelectedDegree(status->cornerSize_);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool StrokeDeformationImpl::computeStroke2Transform(const ContextStatus *status,
Toshihiro Shimizu 890ddd
													TStroke *&stroke2transform,
Toshihiro Shimizu 890ddd
													double &w,
Toshihiro Shimizu 890ddd
													ToonzExt::Interval &extremes)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (!status ||
Toshihiro Shimizu 890ddd
		!isValid(w))
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	stroke2transform = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (status->stroke2change_->isSelfLoop()) {
Toshihiro Shimizu 890ddd
		if (extremes.first > extremes.second) {
Toshihiro Shimizu 890ddd
			double
Toshihiro Shimizu 890ddd
				new_w = (extremes.first + extremes.second) * 0.5;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			if (!rotateStroke(status->stroke2change_,
Toshihiro Shimizu 890ddd
							  stroke2transform,
Toshihiro Shimizu 890ddd
							  w,
Toshihiro Shimizu 890ddd
							  new_w,
Toshihiro Shimizu 890ddd
							  old_w0_pos_))
Toshihiro Shimizu 890ddd
				return false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			ContextStatus
Toshihiro Shimizu 890ddd
				tmpStatus = *status;
Toshihiro Shimizu 890ddd
			tmpStatus.stroke2change_ = stroke2transform;
Toshihiro Shimizu 890ddd
			tmpStatus.w_ = w;
Toshihiro Shimizu 890ddd
			this->check(&tmpStatus);
Toshihiro Shimizu 890ddd
			extremes = this->getExtremes();
Toshihiro Shimizu 890ddd
			this->init(status);
Toshihiro Shimizu 890ddd
			return true;
Toshihiro Shimizu 890ddd
		} else if (extremes.first == extremes.second) {
Toshihiro Shimizu 890ddd
			double
Toshihiro Shimizu 890ddd
				positionOfFixPoint = -1;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			// there are two different cases
Toshihiro Shimizu 890ddd
			//  a) only one corner
Toshihiro Shimizu 890ddd
			//  b) only two corners
Toshihiro Shimizu 890ddd
			switch (this->getSpiresList().size()) {
Toshihiro Shimizu 890ddd
			case 0:
Toshihiro Shimizu 890ddd
				assert(extremes.first == -1);
Toshihiro Shimizu 890ddd
				positionOfFixPoint = retrieveParamAtLengthWithOffset(status->stroke2change_,
Toshihiro Shimizu 890ddd
																	 status->stroke2change_->getLength() * 0.5,
Toshihiro Shimizu 890ddd
																	 w);
Toshihiro Shimizu 890ddd
				break;
Toshihiro Shimizu 890ddd
			case 1:
Toshihiro Shimizu 890ddd
				if (extremes.first != -1)
Toshihiro Shimizu 890ddd
					positionOfFixPoint = retrieveParamAtLengthWithOffset(status->stroke2change_,
Toshihiro Shimizu 890ddd
																		 status->stroke2change_->getLength() * 0.5,
Toshihiro Shimizu 890ddd
																		 w);
Toshihiro Shimizu 890ddd
				else
Toshihiro Shimizu 890ddd
					positionOfFixPoint = this->getSpiresList()[0].first;
Toshihiro Shimizu 890ddd
				break;
Toshihiro Shimizu 890ddd
			case 2:
Toshihiro Shimizu 890ddd
			// also forced mode
Toshihiro Shimizu 890ddd
			default:
Toshihiro Shimizu 890ddd
				assert(extremes.first != -1);
Toshihiro Shimizu 890ddd
				//if( extremes.first == -1 )
Toshihiro Shimizu 890ddd
				//  positionOfFixPoint=retrieveParamAtLengthWithOffset(status->stroke2change_,
Toshihiro Shimizu 890ddd
				//                                                     status->stroke2change_->getLength()*0.5,
Toshihiro Shimizu 890ddd
				//                                                     w);
Toshihiro Shimizu 890ddd
				//else
Toshihiro Shimizu 890ddd
				positionOfFixPoint = extremes.first;
Toshihiro Shimizu 890ddd
				break;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			if (!rotateStroke(status->stroke2change_,
Toshihiro Shimizu 890ddd
							  stroke2transform,
Toshihiro Shimizu 890ddd
							  w,
Toshihiro Shimizu 890ddd
							  positionOfFixPoint,
Toshihiro Shimizu 890ddd
							  old_w0_pos_))
Toshihiro Shimizu 890ddd
				return false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			extremes = ToonzExt::Interval(0.0, 1.0);
Toshihiro Shimizu 890ddd
			return true;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!isValid(extremes.first) ||
Toshihiro Shimizu 890ddd
		!isValid(extremes.second))
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	try {
Toshihiro Shimizu 890ddd
		if (!stroke2transform)
Toshihiro Shimizu 890ddd
			stroke2transform = new TStroke(*status->stroke2change_);
Toshihiro Shimizu 890ddd
	} catch (...) {
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
//  End Of File
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------