Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "tinbetween.h"
Toshihiro Shimizu 890ddd
#include "tcurves.h"
Toshihiro Shimizu 890ddd
#include "tstroke.h"
Toshihiro Shimizu 890ddd
#include "tpalette.h"
Toshihiro Shimizu 890ddd
//#include "tcolorstyles.h"
Toshihiro Shimizu 890ddd
//#include "tregion.h"
Toshihiro Shimizu 890ddd
#include "tmathutil.h"
Toshihiro Shimizu 890ddd
//#include "tstrokeutil.h"
Toshihiro Shimizu 890ddd
//#include "tsystem.h"
Toshihiro Shimizu 890ddd
#include <utility></utility>
Toshihiro Shimizu 890ddd
#include <limits></limits>
Toshihiro Shimizu 890ddd
#include <list></list>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "../tvectorimage/tvectorimageP.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//#include "tdebugmessage.h"
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
double average(std::vector<double> &values, double range = 2.5)</double>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	UINT size = values.size();
Toshihiro Shimizu 890ddd
	if (size == 0)
Toshihiro Shimizu 890ddd
		return std::numeric_limits<double>::signaling_NaN();</double>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (size == 1)
Toshihiro Shimizu 890ddd
		return values[0];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double sum = 0;
Toshihiro Shimizu 890ddd
	UINT j = 0;
Toshihiro Shimizu 890ddd
	for (; j < size; j++) {
Toshihiro Shimizu 890ddd
		sum += values[j];
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double average = sum / size;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double variance = 0;
Toshihiro Shimizu 890ddd
	for (j = 0; j < size; j++) {
Toshihiro Shimizu 890ddd
		variance += (average - values[j]) * (average - values[j]);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	variance /= size;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double err;
Toshihiro Shimizu 890ddd
	int acceptedNum = 0;
Toshihiro Shimizu 890ddd
	sum = 0;
Toshihiro Shimizu 890ddd
	for (j = 0; j < size; j++) {
Toshihiro Shimizu 890ddd
		err = values[j] - average;
Toshihiro Shimizu 890ddd
		err *= err;
Toshihiro Shimizu 890ddd
		if (err <= range * variance) {
Toshihiro Shimizu 890ddd
			sum += values[j];
Toshihiro Shimizu 890ddd
			acceptedNum++;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	assert(acceptedNum > 0);
Toshihiro Shimizu 890ddd
	return (acceptedNum > 0) ? sum / (double)acceptedNum : average;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
double weightedAverage(std::vector<double> &values, std::vector<double> &weights, double range = 2.5)</double></double>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	UINT size = values.size();
Toshihiro Shimizu 890ddd
	if (size == 0)
Toshihiro Shimizu 890ddd
		return std::numeric_limits<double>::signaling_NaN();</double>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double sum = 0;
Toshihiro Shimizu 890ddd
	double totalWeight = 0;
Toshihiro Shimizu 890ddd
	UINT j = 0;
Toshihiro Shimizu 890ddd
	for (; j < size; j++) {
Toshihiro Shimizu 890ddd
		sum += weights[j] * values[j];
Toshihiro Shimizu 890ddd
		totalWeight += weights[j];
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	assert(totalWeight > 0);
Toshihiro Shimizu 890ddd
	if (totalWeight == 0)
Toshihiro Shimizu 890ddd
		return std::numeric_limits<double>::signaling_NaN();</double>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double average = sum / totalWeight;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double variance = 0;
Toshihiro Shimizu 890ddd
	for (j = 0; j < size; j++) {
Toshihiro Shimizu 890ddd
		variance += weights[j] * (average - values[j]) * (average - values[j]);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	variance /= totalWeight;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double err;
Toshihiro Shimizu 890ddd
	totalWeight = 0;
Toshihiro Shimizu 890ddd
	sum = 0;
Toshihiro Shimizu 890ddd
	for (j = 0; j < size; j++) {
Toshihiro Shimizu 890ddd
		err = values[j] - average;
Toshihiro Shimizu 890ddd
		err *= err;
Toshihiro Shimizu 890ddd
		if (err <= range * variance) {
Toshihiro Shimizu 890ddd
			sum += weights[j] * values[j];
Toshihiro Shimizu 890ddd
			totalWeight += weights[j];
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	assert(totalWeight > 0);
Toshihiro Shimizu 890ddd
	return (totalWeight != 0) ? sum / totalWeight : average;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
inline UINT angleNumber(const std::vector<std::pair<int, double="">> &corners, double angle)</std::pair<int,>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	UINT count = 0;
Toshihiro Shimizu 890ddd
	UINT size = corners.size();
Toshihiro Shimizu 890ddd
	for (UINT j = 0; j < size; j++)
Toshihiro Shimizu 890ddd
		if (corners[j].second >= angle)
Toshihiro Shimizu 890ddd
			count++;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return count;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
inline bool isTooComplex(UINT n1, UINT n2, UINT maxSubsetNumber = 100)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	UINT n, r;
Toshihiro Shimizu 890ddd
	if (n1 > n2) {
Toshihiro Shimizu 890ddd
		n = n1;
Toshihiro Shimizu 890ddd
		r = n2;
Toshihiro Shimizu 890ddd
	} else if (n1 < n2) {
Toshihiro Shimizu 890ddd
		n = n2;
Toshihiro Shimizu 890ddd
		r = n1;
Toshihiro Shimizu 890ddd
	} else {
Toshihiro Shimizu 890ddd
		assert(!"equal angle number");
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (n - r < r)
Toshihiro Shimizu 890ddd
		r = n - r;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	/*
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
  n*(n-1)* ...(n-r+1) < n^r that must be <= 2^(num bits of UINT)-1
Toshihiro Shimizu 890ddd
  
Toshihiro Shimizu 890ddd
  s:=sizeof(UINT)*8
Toshihiro Shimizu 890ddd
    
Toshihiro Shimizu 890ddd
  if
Toshihiro Shimizu 890ddd
  n <= 2^( (s-1)/r)   =>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
  log n <= (s-1)/r    (the base of log is 2)  =>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
  r*log n <= s-1      =>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
  log n^r <= log 2^(s-1)   =>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
  n^r <= 2^(s-1) <  (2^s)-1
Toshihiro Shimizu 890ddd
    
Toshihiro Shimizu 890ddd
  */
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	const UINT one = 1;
Toshihiro Shimizu 890ddd
	if (n > (one << ((sizeof(UINT) * 8 - 1) / r)))
Toshihiro Shimizu 890ddd
		return true;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	register UINT product1 = n; //product1 = n*(n-1)* ...(n-r+1)
Toshihiro Shimizu 890ddd
	for (register UINT i = 1; i < r; i++)
Toshihiro Shimizu 890ddd
		product1 *= --n;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	register UINT rFact = r;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	while (r > 1)
Toshihiro Shimizu 890ddd
		rFact *= --r;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return (product1 / rFact > maxSubsetNumber);
Toshihiro Shimizu 890ddd
	//product1/rFact is number of combination
Toshihiro Shimizu 890ddd
	//  ( n )
Toshihiro Shimizu 890ddd
	//  ( r )
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void eraseSmallAngles(std::vector<std::pair<int, double="">> &corners, double angle)</std::pair<int,>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	std::vector<std::pair<int, double="">>::iterator it = corners.begin();</std::pair<int,>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	while (it != corners.end()) {
Toshihiro Shimizu 890ddd
		if ((*it).second < angle)
Toshihiro Shimizu 890ddd
			it = corners.erase(it);
Toshihiro Shimizu 890ddd
		else
Toshihiro Shimizu 890ddd
			++it;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
//output:
Toshihiro Shimizu 890ddd
// min is the minimum angle greater or equal to minDegree (i.e the minimum angle of the corners)
Toshihiro Shimizu 890ddd
// max is tha maximum angle greater or equal to minDegree
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void detectCorners(const TStroke *stroke, double minDegree,
Toshihiro Shimizu 890ddd
				   std::vector<std::pair<int, double="">> &corners, double &min, double &max)</std::pair<int,>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	const double minSin = fabs(sin(minDegree * TConsts::pi_180));
Toshihiro Shimizu 890ddd
	double angle, vectorialProduct, metaCornerLen, partialLen;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	UINT quadCount1 = stroke->getChunkCount();
Toshihiro Shimizu 890ddd
	TPointD speed1, speed2;
Toshihiro Shimizu 890ddd
	int j;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TPointD tan1, tan2;
Toshihiro Shimizu 890ddd
	min = 180;
Toshihiro Shimizu 890ddd
	max = minDegree;
Toshihiro Shimizu 890ddd
	for (j = 1; j < (int)quadCount1; j++) {
Toshihiro Shimizu 890ddd
		speed1 = stroke->getChunk(j - 1)->getSpeed(1);
Toshihiro Shimizu 890ddd
		speed2 = stroke->getChunk(j)->getSpeed(0);
Toshihiro Shimizu 890ddd
		if (!(speed1 == TPointD() || speed2 == TPointD())) {
Toshihiro Shimizu 890ddd
			tan1 = normalize(speed1);
Toshihiro Shimizu 890ddd
			tan2 = normalize(speed2);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			vectorialProduct = fabs(cross(tan1, tan2));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			if (tan1 * tan2 < 0) {
Toshihiro Shimizu 890ddd
				angle = 180 - asin(tcrop(vectorialProduct, -1.0, 1.0)) * TConsts::invOf_pi_180;
Toshihiro Shimizu 890ddd
				corners.push_back(std::make_pair(j, angle));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				//------------------------------------------
Toshihiro Shimizu 890ddd
				//        TDebugMessage::getStream()<
Toshihiro Shimizu 890ddd
				//        TDebugMessage::flush();
Toshihiro Shimizu 890ddd
				//------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				if (min > angle)
Toshihiro Shimizu 890ddd
					min = angle;
Toshihiro Shimizu 890ddd
				if (max < angle)
Toshihiro Shimizu 890ddd
					max = angle;
Toshihiro Shimizu 890ddd
			} else if (vectorialProduct >= minSin) {
Toshihiro Shimizu 890ddd
				angle = asin(tcrop(vectorialProduct, -1.0, 1.0)) * TConsts::invOf_pi_180;
Toshihiro Shimizu 890ddd
				corners.push_back(std::make_pair(j, angle));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				//------------------------------------------
Toshihiro Shimizu 890ddd
				//        TDebugMessage::getStream()<
Toshihiro Shimizu 890ddd
				//        TDebugMessage::flush();
Toshihiro Shimizu 890ddd
				//------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				if (min > angle)
Toshihiro Shimizu 890ddd
					min = angle;
Toshihiro Shimizu 890ddd
				if (max < angle)
Toshihiro Shimizu 890ddd
					max = angle;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	const double ratioLen = 2.5;
Toshihiro Shimizu 890ddd
	const double ratioAngle = 0.2;
Toshihiro Shimizu 890ddd
	std::vector<std::pair<int, double="">>::iterator it = corners.begin();</std::pair<int,>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (j = 1; j < (int)quadCount1; j++) //"meta angoli" ( meta perche' derivabili)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		if (it != corners.end() && j == (*it).first) {
Toshihiro Shimizu 890ddd
			++it;
Toshihiro Shimizu 890ddd
			continue;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (j - 2 >= 0 && (corners.empty() || it == corners.begin() || j - 1 != (*(it - 1)).first) && j + 1 < (int)quadCount1 && (corners.empty() || it == corners.end() || j + 1 != (*it).first)) {
Toshihiro Shimizu 890ddd
			speed1 = stroke->getChunk(j - 2)->getSpeed(1);
Toshihiro Shimizu 890ddd
			speed2 = stroke->getChunk(j + 1)->getSpeed(0);
Toshihiro Shimizu 890ddd
			if (!(speed1 == TPointD() || speed2 == TPointD())) {
Toshihiro Shimizu 890ddd
				tan1 = normalize(speed1);
Toshihiro Shimizu 890ddd
				tan2 = normalize(speed2);
Toshihiro Shimizu 890ddd
				vectorialProduct = fabs(cross(tan1, tan2));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				if (tan1 * tan2 < 0) {
Toshihiro Shimizu 890ddd
					angle = 180 - asin(tcrop(vectorialProduct, -1.0, 1.0)) * TConsts::invOf_pi_180;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					metaCornerLen = ratioLen * (stroke->getChunk(j - 1)->getLength() + stroke->getChunk(j)->getLength());
Toshihiro Shimizu 890ddd
					partialLen = 0;
Toshihiro Shimizu 890ddd
					bool goodAngle = false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					for (int i = j - 3; i >= 0 && (corners.empty() || it == corners.begin() || i + 1 != (*(it - 1)).first); i--) {
Toshihiro Shimizu 890ddd
						tan1 = stroke->getChunk(i)->getSpeed(1);
Toshihiro Shimizu 890ddd
						if (tan1 == TPointD())
Toshihiro Shimizu 890ddd
							continue;
Toshihiro Shimizu 890ddd
						tan1 = normalize(tan1);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
						tan2 = stroke->getChunk(i + 1)->getSpeed(1);
Toshihiro Shimizu 890ddd
						if (tan2 == TPointD())
Toshihiro Shimizu 890ddd
							continue;
Toshihiro Shimizu 890ddd
						tan2 = normalize(tan2);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
						vectorialProduct = fabs(cross(tan1, tan2));
Toshihiro Shimizu 890ddd
						double nearAngle = asin(tcrop(vectorialProduct, -1.0, 1.0)) * TConsts::invOf_pi_180;
Toshihiro Shimizu 890ddd
						if (tan1 * tan2 < 0)
Toshihiro Shimizu 890ddd
							nearAngle = 180 - nearAngle;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
						if (nearAngle > ratioAngle * angle)
Toshihiro Shimizu 890ddd
							break;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
						partialLen += stroke->getChunk(i)->getLength();
Toshihiro Shimizu 890ddd
						if (partialLen > metaCornerLen) {
Toshihiro Shimizu 890ddd
							goodAngle = true;
Toshihiro Shimizu 890ddd
							break;
Toshihiro Shimizu 890ddd
						}
Toshihiro Shimizu 890ddd
					}
Toshihiro Shimizu 890ddd
					if (goodAngle) {
Toshihiro Shimizu 890ddd
						partialLen = 0;
Toshihiro Shimizu 890ddd
						for (int i = j + 2; i + 1 < (int)quadCount1 && (corners.empty() || it == corners.end() || i + 1 != (*it).first); i++) {
Toshihiro Shimizu 890ddd
							tan1 = stroke->getChunk(i)->getSpeed(0);
Toshihiro Shimizu 890ddd
							if (tan1 == TPointD())
Toshihiro Shimizu 890ddd
								continue;
Toshihiro Shimizu 890ddd
							tan1 = normalize(tan1);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
							tan2 = stroke->getChunk(i + 1)->getSpeed(0);
Toshihiro Shimizu 890ddd
							if (tan2 == TPointD())
Toshihiro Shimizu 890ddd
								continue;
Toshihiro Shimizu 890ddd
							tan2 = normalize(tan2);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
							vectorialProduct = fabs(cross(tan1, tan2));
Toshihiro Shimizu 890ddd
							double nearAngle = asin(tcrop(vectorialProduct, -1.0, 1.0)) * TConsts::invOf_pi_180;
Toshihiro Shimizu 890ddd
							if (tan1 * tan2 < 0)
Toshihiro Shimizu 890ddd
								nearAngle = 180 - nearAngle;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
							if (nearAngle > 0.1 * angle)
Toshihiro Shimizu 890ddd
								break;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
							partialLen += stroke->getChunk(i)->getLength();
Toshihiro Shimizu 890ddd
							if (partialLen > metaCornerLen) {
Toshihiro Shimizu 890ddd
								goodAngle = true;
Toshihiro Shimizu 890ddd
								break;
Toshihiro Shimizu 890ddd
							}
Toshihiro Shimizu 890ddd
						}
Toshihiro Shimizu 890ddd
					}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					if (goodAngle) {
Toshihiro Shimizu 890ddd
						//l'angolo viene un po' declassato in quanto meta
Toshihiro Shimizu 890ddd
						it = corners.insert(it, std::make_pair(j, angle * 0.7)) + 1;
Toshihiro Shimizu 890ddd
						if (min > angle)
Toshihiro Shimizu 890ddd
							min = angle;
Toshihiro Shimizu 890ddd
						if (max < angle)
Toshihiro Shimizu 890ddd
							max = angle;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
						//            TDebugMessage::getStream()<
Toshihiro Shimizu 890ddd
						//            TDebugMessage::flush();
Toshihiro Shimizu 890ddd
					}
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
double variance(std::vector<double> &values)</double>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	UINT size = values.size();
Toshihiro Shimizu 890ddd
	if (size == 0)
Toshihiro Shimizu 890ddd
		return std::numeric_limits<double>::signaling_NaN();</double>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double sum = 0;
Toshihiro Shimizu 890ddd
	UINT j = 0;
Toshihiro Shimizu 890ddd
	for (; j < size; j++) {
Toshihiro Shimizu 890ddd
		sum += values[j];
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double average = sum / size;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double variance = 0;
Toshihiro Shimizu 890ddd
	for (j = 0; j < size; j++) {
Toshihiro Shimizu 890ddd
		variance += (average - values[j]) * (average - values[j]);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return variance / size;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void findBestSolution(const TStroke *stroke1, const TStroke *stroke2,
Toshihiro Shimizu 890ddd
					  std::pair<int, double=""> *partialAngles1, UINT partialAngles1Size,</int,>
Toshihiro Shimizu 890ddd
					  const std::vector<std::pair<int, double="">> &angles2,</std::pair<int,>
Toshihiro Shimizu 890ddd
					  UINT r, std::list<std::pair<int, double="">> &partialSolution,</std::pair<int,>
Toshihiro Shimizu 890ddd
					  double &bestValue,
Toshihiro Shimizu 890ddd
					  std::vector<int> &bestVector)</int>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
	if (r == partialAngles1Size) {
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		UINT j;
Toshihiro Shimizu 890ddd
		vector<std::pair<int, double="">> angles1;</std::pair<int,>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		std::list<std::pair<int, double="">>::iterator it = partialSolution.begin();</std::pair<int,>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		for (; it != partialSolution.end(); ++it) {
Toshihiro Shimizu 890ddd
			angles1.push_back(*it);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		for (j = 0; j < partialAngles1Size; j++) {
Toshihiro Shimizu 890ddd
			angles1.push_back(partialAngles1[j]);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		UINT angles1Size = angles1.size();
Toshihiro Shimizu 890ddd
		vector<double> rationAngles(angles1Size), ratioLength(angles1Size + 1);</double>
Toshihiro Shimizu 890ddd
		vector<double> ratioX, ratioY;</double>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		for (j = 0; j < angles1Size; j++) {
Toshihiro Shimizu 890ddd
			rationAngles[j] = fabs(angles1[j].second - angles2[j].second) / (angles1[j].second + angles2[j].second);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		UINT firstQuad1 = 0;
Toshihiro Shimizu 890ddd
		UINT firstQuad2 = 0;
Toshihiro Shimizu 890ddd
		UINT nextQuad1, nextQuad2;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		TRectD bbox1 = stroke1->getBBox();
Toshihiro Shimizu 890ddd
		TRectD bbox2 = stroke2->getBBox();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		double app, div;
Toshihiro Shimizu 890ddd
		double invTotalLen1 = stroke1->getLength();
Toshihiro Shimizu 890ddd
		assert(invTotalLen1 > 0);
Toshihiro Shimizu 890ddd
		invTotalLen1 = 1.0 / invTotalLen1;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		double invTotalLen2 = stroke2->getLength();
Toshihiro Shimizu 890ddd
		assert(invTotalLen2 > 0);
Toshihiro Shimizu 890ddd
		invTotalLen2 = 1.0 / invTotalLen2;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		for (j = 0; j <= angles1Size; j++) {
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			if (j < angles1Size) {
Toshihiro Shimizu 890ddd
				nextQuad1 = angles1[j].first;
Toshihiro Shimizu 890ddd
				nextQuad2 = angles2[j].first;
Toshihiro Shimizu 890ddd
			} else {
Toshihiro Shimizu 890ddd
				nextQuad1 = stroke1->getChunkCount();
Toshihiro Shimizu 890ddd
				nextQuad2 = stroke2->getChunkCount();
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			ratioLength[j] = fabs(stroke1->getLengthAtControlPoint(nextQuad1 * 2) * invTotalLen1 - stroke2->getLengthAtControlPoint(nextQuad2 * 2) * invTotalLen2);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			TPointD p1(stroke1->getChunk(nextQuad1 - 1)->getP2() -
Toshihiro Shimizu 890ddd
					   stroke1->getChunk(firstQuad1)->getP0());
Toshihiro Shimizu 890ddd
			p1.x = fabs(p1.x);
Toshihiro Shimizu 890ddd
			p1.y = fabs(p1.y);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			TPointD p2(stroke2->getChunk(nextQuad2 - 1)->getP2() -
Toshihiro Shimizu 890ddd
					   stroke2->getChunk(firstQuad2)->getP0());
Toshihiro Shimizu 890ddd
			p2.x = fabs(p2.x);
Toshihiro Shimizu 890ddd
			p2.y = fabs(p2.y);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			app = fabs(bbox1.getLx() * p2.x - bbox2.getLx() * p1.x);
Toshihiro Shimizu 890ddd
			div = (bbox1.getLx() * p2.x + bbox2.getLx() * p1.x);
Toshihiro Shimizu 890ddd
			if (div)
Toshihiro Shimizu 890ddd
				ratioX.push_back(app / div);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			app = fabs(bbox1.getLy() * p2.y - bbox2.getLy() * p1.y);
Toshihiro Shimizu 890ddd
			div = (bbox1.getLy() * p2.y + bbox2.getLy() * p1.y);
Toshihiro Shimizu 890ddd
			if (div)
Toshihiro Shimizu 890ddd
				ratioY.push_back(app / div);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			firstQuad1 = nextQuad1;
Toshihiro Shimizu 890ddd
			firstQuad2 = nextQuad2;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		double varAng, varX, varY, varLen;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		varX = average(ratioX);
Toshihiro Shimizu 890ddd
		varY = average(ratioY);
Toshihiro Shimizu 890ddd
		varLen = average(ratioLength);
Toshihiro Shimizu 890ddd
		varAng = average(rationAngles);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		double estimate = varX + varY + varAng + varLen;
Toshihiro Shimizu 890ddd
		/*    
Toshihiro Shimizu 890ddd
    #ifdef _DEBUG
Toshihiro Shimizu 890ddd
    for(UINT dI=0; dI
Toshihiro Shimizu 890ddd
    {
Toshihiro Shimizu 890ddd
      TDebugMessage::getStream() << angles1[dI].first<<"  ";      
Toshihiro Shimizu 890ddd
    }
Toshihiro Shimizu 890ddd
    TDebugMessage::flush();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
    TDebugMessage::getStream() <<"estimate "<< estimate<<"=" ;
Toshihiro Shimizu 890ddd
    TDebugMessage::flush();
Toshihiro Shimizu 890ddd
    TDebugMessage::getStream()<
Toshihiro Shimizu 890ddd
    TDebugMessage::flush();
Toshihiro Shimizu 890ddd
    TDebugMessage::getStream()<
Toshihiro Shimizu 890ddd
    TDebugMessage::flush();
Toshihiro Shimizu 890ddd
    TDebugMessage::getStream()<
Toshihiro Shimizu 890ddd
    TDebugMessage::flush();
Toshihiro Shimizu 890ddd
    TDebugMessage::getStream()<
Toshihiro Shimizu 890ddd
    TDebugMessage::flush();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
    #endif
Toshihiro Shimizu 890ddd
    */
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (estimate < bestValue) {
Toshihiro Shimizu 890ddd
			bestValue = estimate;
Toshihiro Shimizu 890ddd
			if (bestVector.size() != angles1Size) {
Toshihiro Shimizu 890ddd
				assert(!"bad size for bestVector");
Toshihiro Shimizu 890ddd
				bestVector.resize(angles1Size);
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			for (j = 0; j < angles1Size; j++) {
Toshihiro Shimizu 890ddd
				bestVector[j] = angles1[j].first;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (r == 1) {
Toshihiro Shimizu 890ddd
		for (UINT i = 0; i < partialAngles1Size; i++) {
Toshihiro Shimizu 890ddd
			findBestSolution(stroke1, stroke2,
Toshihiro Shimizu 890ddd
							 partialAngles1 + i, 1,
Toshihiro Shimizu 890ddd
							 angles2,
Toshihiro Shimizu 890ddd
							 1, partialSolution,
Toshihiro Shimizu 890ddd
							 bestValue,
Toshihiro Shimizu 890ddd
							 bestVector);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	partialSolution.push_back(partialAngles1[0]);
Toshihiro Shimizu 890ddd
	findBestSolution(stroke1, stroke2,
Toshihiro Shimizu 890ddd
					 partialAngles1 + 1, partialAngles1Size - 1,
Toshihiro Shimizu 890ddd
					 angles2,
Toshihiro Shimizu 890ddd
					 r - 1, partialSolution,
Toshihiro Shimizu 890ddd
					 bestValue,
Toshihiro Shimizu 890ddd
					 bestVector);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	partialSolution.pop_back();
Toshihiro Shimizu 890ddd
	findBestSolution(stroke1, stroke2,
Toshihiro Shimizu 890ddd
					 partialAngles1 + 1, partialAngles1Size - 1,
Toshihiro Shimizu 890ddd
					 angles2,
Toshihiro Shimizu 890ddd
					 r, partialSolution,
Toshihiro Shimizu 890ddd
					 bestValue,
Toshihiro Shimizu 890ddd
					 bestVector);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void findBestSolution(const TStroke *stroke1, const TStroke *stroke2,
Toshihiro Shimizu 890ddd
					  std::vector<std::pair<int, double="">> &angles1,</std::pair<int,>
Toshihiro Shimizu 890ddd
					  const std::vector<std::pair<int, double="">> &angles2,</std::pair<int,>
Toshihiro Shimizu 890ddd
					  double &bestValue,
Toshihiro Shimizu 890ddd
					  std::vector<int> &bestVector)</int>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	assert(angles1.size() > angles2.size());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	list<std::pair<int, double="">> partialSolution;</std::pair<int,>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	findBestSolution(stroke1, stroke2,
Toshihiro Shimizu 890ddd
					 &(angles1[0]), angles1.size(),
Toshihiro Shimizu 890ddd
					 angles2,
Toshihiro Shimizu 890ddd
					 angles2.size(), partialSolution,
Toshihiro Shimizu 890ddd
					 bestValue, bestVector);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void trivialSolution(const TStroke *stroke1, const TStroke *stroke2,
Toshihiro Shimizu 890ddd
					 const std::vector<std::pair<int, double="">> &angles1,</std::pair<int,>
Toshihiro Shimizu 890ddd
					 const std::vector<std::pair<int, double="">> &angles2,</std::pair<int,>
Toshihiro Shimizu 890ddd
					 std::vector<int> &solution)</int>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	assert(angles1.size() > angles2.size());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	UINT j;
Toshihiro Shimizu 890ddd
	double subStrokeRatio2;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double invTotalLen2 = stroke2->getLength();
Toshihiro Shimizu 890ddd
	assert(invTotalLen2);
Toshihiro Shimizu 890ddd
	invTotalLen2 = 1.0 / invTotalLen2;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double invTotalLen1 = stroke1->getLength();
Toshihiro Shimizu 890ddd
	assert(invTotalLen1 > 0);
Toshihiro Shimizu 890ddd
	invTotalLen1 = 1.0 / invTotalLen1;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (solution.size() != angles2.size()) {
Toshihiro Shimizu 890ddd
		assert(!"bad size for solution");
Toshihiro Shimizu 890ddd
		solution.resize(angles2.size());
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int toBeErased = angles1.size() - angles2.size();
Toshihiro Shimizu 890ddd
	UINT count = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double diff, ratio, oldRatio = 100;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	subStrokeRatio2 = stroke2->getLengthAtControlPoint(angles2[count].first * 2) * invTotalLen2;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (j = 0; j < angles1.size() && count < solution.size(); j++) {
Toshihiro Shimizu 890ddd
		if (toBeErased == 0) {
Toshihiro Shimizu 890ddd
			solution[count++] = angles1[j].first;
Toshihiro Shimizu 890ddd
		} else {
Toshihiro Shimizu 890ddd
			ratio = stroke1->getLengthAtControlPoint(angles1[j].first * 2) * invTotalLen1;
Toshihiro Shimizu 890ddd
			assert(ratio > 0 && ratio <= 1);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			diff = ratio - subStrokeRatio2;
Toshihiro Shimizu 890ddd
			if (diff >= 0) {
Toshihiro Shimizu 890ddd
				if (fabs(diff) < fabs(oldRatio - subStrokeRatio2)) {
Toshihiro Shimizu 890ddd
					solution[count] = angles1[j].first;
Toshihiro Shimizu 890ddd
					oldRatio = 100;
Toshihiro Shimizu 890ddd
				} else {
Toshihiro Shimizu 890ddd
					assert(j > 0);
Toshihiro Shimizu 890ddd
					solution[count] = angles1[j - 1].first;
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
				count++;
Toshihiro Shimizu 890ddd
				if (angles2.size() < count)
Toshihiro Shimizu 890ddd
					subStrokeRatio2 = stroke2->getLengthAtControlPoint(angles2[count].first * 2) * invTotalLen2;
Toshihiro Shimizu 890ddd
				else
Toshihiro Shimizu 890ddd
					subStrokeRatio2 = 1;
Toshihiro Shimizu 890ddd
			} else {
Toshihiro Shimizu 890ddd
				toBeErased--;
Toshihiro Shimizu 890ddd
				oldRatio = ratio;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	assert(count == solution.size());
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TStroke *extract(const TStroke *source, UINT firstQuad, UINT lastQuad)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	UINT quadCount = source->getChunkCount();
Toshihiro Shimizu 890ddd
	if (firstQuad >= quadCount) {
Toshihiro Shimizu 890ddd
		assert(!"bad quadric index");
Toshihiro Shimizu 890ddd
		firstQuad = quadCount - 1;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	if (lastQuad < firstQuad) {
Toshihiro Shimizu 890ddd
		assert(!"bad quadric index");
Toshihiro Shimizu 890ddd
		lastQuad = firstQuad;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	if (lastQuad >= quadCount) {
Toshihiro Shimizu 890ddd
		assert(!"bad quadric index");
Toshihiro Shimizu 890ddd
		lastQuad = quadCount - 1;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	UINT cpIndex0 = firstQuad * 2;
Toshihiro Shimizu 890ddd
	UINT cpIndex1 = lastQuad * 2 + 2;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	vector<tthickpoint> points(cpIndex1 - cpIndex0 + 1);</tthickpoint>
Toshihiro Shimizu 890ddd
	UINT count = 0;
Toshihiro Shimizu 890ddd
	for (UINT j = cpIndex0; j <= cpIndex1; j++) {
Toshihiro Shimizu 890ddd
		points[count++] = source->getControlPoint(j);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return new TStroke(points);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void sample(const TStroke *stroke, int samplingSize, vector<tpointd> &sampledPoint)</tpointd>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	double samplingFrequency = 1.0 / (double)samplingSize;
Toshihiro Shimizu 890ddd
	sampledPoint.resize(samplingSize);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double totalLen = stroke->getLength();
Toshihiro Shimizu 890ddd
	double step = totalLen * samplingFrequency;
Toshihiro Shimizu 890ddd
	double len = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (int p = 0; p < samplingSize - 1; p++) {
Toshihiro Shimizu 890ddd
		sampledPoint[p] = stroke->getPointAtLength(len);
Toshihiro Shimizu 890ddd
		len += step;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	sampledPoint.back() = stroke->getControlPoint(stroke->getControlPointCount() - 1);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class TInbetween::Imp
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	//----------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	struct StrokeTransform {
Toshihiro Shimizu 890ddd
		typedef enum {
Toshihiro Shimizu 890ddd
			EQUAL,
Toshihiro Shimizu 890ddd
			POINT,
Toshihiro Shimizu 890ddd
			GENERAL
Toshihiro Shimizu 890ddd
		} TransformationType;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		TPointD m_translate;
Toshihiro Shimizu 890ddd
		TPointD m_rotationAndScaleCenter;
Toshihiro Shimizu 890ddd
		double m_scaleX, m_scaleY, m_rotation;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		TransformationType m_type;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		//saved for optimization
Toshihiro Shimizu 890ddd
		TAffine m_inverse;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		vector<int> m_firstStrokeCornerIndexes;</int>
Toshihiro Shimizu 890ddd
		vector<int> m_secondStrokeCornerIndexes;</int>
Toshihiro Shimizu 890ddd
	};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//----------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TVectorImageP m_firstImage, m_lastImage;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	std::vector<stroketransform> m_transformation;</stroketransform>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void computeTransformation();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void transferColor(const TVectorImageP &destination) const;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TVectorImageP tween(double t) const;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	Imp(const TVectorImageP firstImage, const TVectorImageP lastImage)
Toshihiro Shimizu 890ddd
		: m_firstImage(firstImage), m_lastImage(lastImage)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		computeTransformation();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TInbetween::TInbetween(const TVectorImageP firstImage, const TVectorImageP lastImage)
Toshihiro Shimizu 890ddd
	: m_imp(new TInbetween::Imp(firstImage, lastImage))
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TInbetween::~TInbetween()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	delete m_imp;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TInbetween::Imp::computeTransformation()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	const UINT samplingPointNumber = 10;
Toshihiro Shimizu 890ddd
	const UINT bboxSamplingWeight = samplingPointNumber / 2;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	StrokeTransform transform;
Toshihiro Shimizu 890ddd
	double cs, sn, totalLen1, totalLen2, constK, constQ, constB, constD, constA;
Toshihiro Shimizu 890ddd
	UINT cpCount1, cpCount2;
Toshihiro Shimizu 890ddd
	TPointD stroke1Centroid, stroke2Centroid, stroke1Begin, stroke2Begin, stroke1End, stroke2End, versor1, versor2;
Toshihiro Shimizu 890ddd
	vector<tpointd> samplingPoint1(samplingPointNumber), samplingPoint2(samplingPointNumber);</tpointd>
Toshihiro Shimizu 890ddd
	TStroke *stroke1, *stroke2;
Toshihiro Shimizu 890ddd
	vector<double> ratioSampling, weigths, subStrokeXScaling, subStrokeYScaling;</double>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	UINT strokeCount1 = m_firstImage->getStrokeCount();
Toshihiro Shimizu 890ddd
	UINT strokeCount2 = m_lastImage->getStrokeCount();
Toshihiro Shimizu 890ddd
	if (strokeCount1 > strokeCount2)
Toshihiro Shimizu 890ddd
		strokeCount1 = strokeCount2;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_transformation.clear();
Toshihiro Shimizu 890ddd
	m_transformation.reserve(strokeCount1);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	const int maxSubSetNum = (strokeCount1) ? 1000 / strokeCount1 : 1;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	UINT j, p;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (UINT i = 0; i < strokeCount1; i++) {
Toshihiro Shimizu 890ddd
		stroke1 = m_firstImage->getStroke(i);
Toshihiro Shimizu 890ddd
		stroke2 = m_lastImage->getStroke(i);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		//check if the strokes are equal
Toshihiro Shimizu 890ddd
		cpCount1 = stroke1->getControlPointCount();
Toshihiro Shimizu 890ddd
		cpCount2 = stroke2->getControlPointCount();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		transform.m_firstStrokeCornerIndexes.clear();
Toshihiro Shimizu 890ddd
		transform.m_secondStrokeCornerIndexes.clear();
Toshihiro Shimizu 890ddd
		transform.m_translate = TPointD();
Toshihiro Shimizu 890ddd
		transform.m_rotationAndScaleCenter = TPointD();
Toshihiro Shimizu 890ddd
		transform.m_scaleX = 0;
Toshihiro Shimizu 890ddd
		transform.m_scaleY = 0;
Toshihiro Shimizu 890ddd
		transform.m_rotation = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		bool isEqual = true;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (cpCount1 == cpCount2) {
Toshihiro Shimizu 890ddd
			for (j = 0; j < cpCount1 && isEqual; j++) {
Toshihiro Shimizu 890ddd
				isEqual = (stroke1->getControlPoint(j) == stroke2->getControlPoint(j));
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		} else
Toshihiro Shimizu 890ddd
			isEqual = false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (isEqual) {
Toshihiro Shimizu 890ddd
			transform.m_type = StrokeTransform::EQUAL;
Toshihiro Shimizu 890ddd
		} else {
Toshihiro Shimizu 890ddd
			totalLen1 = stroke1->getLength();
Toshihiro Shimizu 890ddd
			totalLen2 = stroke2->getLength();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			if (totalLen1 == 0 || totalLen2 == 0) {
Toshihiro Shimizu 890ddd
				if (totalLen1 == 0 && totalLen2 == 0) {
Toshihiro Shimizu 890ddd
					transform.m_type = StrokeTransform::POINT;
Toshihiro Shimizu 890ddd
				} else {
Toshihiro Shimizu 890ddd
					transform.m_inverse = TAffine();
Toshihiro Shimizu 890ddd
					transform.m_firstStrokeCornerIndexes.resize(2);
Toshihiro Shimizu 890ddd
					transform.m_firstStrokeCornerIndexes[0] = 0;
Toshihiro Shimizu 890ddd
					transform.m_firstStrokeCornerIndexes[1] = stroke1->getChunkCount();
Toshihiro Shimizu 890ddd
					transform.m_secondStrokeCornerIndexes.resize(2);
Toshihiro Shimizu 890ddd
					transform.m_secondStrokeCornerIndexes[0] = 0;
Toshihiro Shimizu 890ddd
					transform.m_secondStrokeCornerIndexes[1] = stroke2->getChunkCount();
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			} else {
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				const double startMinAngle = 30.0;
Toshihiro Shimizu 890ddd
				vector<pair<int, double="">> angles1, angles2;</pair<int,>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				transform.m_type = StrokeTransform::GENERAL;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				double minAngle, maxAngle;
Toshihiro Shimizu 890ddd
				int minAngle1, maxAngle1, minAngle2, maxAngle2;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				angles1.clear();
Toshihiro Shimizu 890ddd
				angles2.clear();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				//        TDebugMessage::getStream()<
Toshihiro Shimizu 890ddd
				//        TDebugMessage::flush();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				detectCorners(stroke1, startMinAngle, angles1, minAngle, maxAngle);
Toshihiro Shimizu 890ddd
				minAngle1 = (int)minAngle;
Toshihiro Shimizu 890ddd
				maxAngle1 = (int)maxAngle;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				//        TDebugMessage::getStream()<
Toshihiro Shimizu 890ddd
				//        TDebugMessage::flush();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				detectCorners(stroke2, startMinAngle, angles2, minAngle, maxAngle);
Toshihiro Shimizu 890ddd
				minAngle2 = (int)minAngle;
Toshihiro Shimizu 890ddd
				maxAngle2 = (int)maxAngle;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				if (angles1.empty())
Toshihiro Shimizu 890ddd
					angles2.clear();
Toshihiro Shimizu 890ddd
				if (angles2.empty())
Toshihiro Shimizu 890ddd
					angles1.clear();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				/*
Toshihiro Shimizu 890ddd
        debugStream.open("c:\\temp\\inbetween.txt", ios_base::out);
Toshihiro Shimizu 890ddd
        debugStream <<"num angoli 1: "<< angles1.size() << endl;
Toshihiro Shimizu 890ddd
        debugStream <<"num angoli 2: "<< angles2.size() << endl;
Toshihiro Shimizu 890ddd
        */
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				double bestValue = (std::numeric_limits<double>::max)();</double>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				if (angles1.size() != angles2.size()) {
Toshihiro Shimizu 890ddd
					bestValue = (std::numeric_limits<double>::max)();</double>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					//--------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					if (isTooComplex(angles1.size(), angles2.size(), maxSubSetNum)) {
Toshihiro Shimizu 890ddd
						//debugStream <<"is too complex" << endl;
Toshihiro Shimizu 890ddd
						int firstAngle = (int)((angles1.size() < angles2.size()) ? minAngle2 : minAngle1);
Toshihiro Shimizu 890ddd
						int lastAngle = (int)((angles1.size() < angles2.size()) ? maxAngle1 : maxAngle2);
Toshihiro Shimizu 890ddd
						int bestAngle = (int)startMinAngle;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
						if ((int)(angles1.size() + angles2.size()) < lastAngle - firstAngle + 1) {
Toshihiro Shimizu 890ddd
							double tempAngle;
Toshihiro Shimizu 890ddd
							vector<double> sortedAngles1, sortedAngles2;</double>
Toshihiro Shimizu 890ddd
							sortedAngles1.reserve(angles1.size());
Toshihiro Shimizu 890ddd
							sortedAngles2.reserve(angles2.size());
Toshihiro Shimizu 890ddd
							for (j = 0; j < angles1.size(); j++) {
Toshihiro Shimizu 890ddd
								tempAngle = angles1[j].second;
Toshihiro Shimizu 890ddd
								if (tempAngle >= firstAngle && tempAngle <= lastAngle)
Toshihiro Shimizu 890ddd
									sortedAngles1.push_back(tempAngle);
Toshihiro Shimizu 890ddd
							}
Toshihiro Shimizu 890ddd
							for (j = 0; j < angles2.size(); j++) {
Toshihiro Shimizu 890ddd
								tempAngle = angles2[j].second;
Toshihiro Shimizu 890ddd
								if (tempAngle >= firstAngle && tempAngle <= lastAngle)
Toshihiro Shimizu 890ddd
									sortedAngles2.push_back(tempAngle);
Toshihiro Shimizu 890ddd
							}
Toshihiro Shimizu 890ddd
							vector<double> sortedAngles(sortedAngles1.size() + sortedAngles2.size());</double>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
							std::sort(sortedAngles1.begin(), sortedAngles1.end());
Toshihiro Shimizu 890ddd
							std::sort(sortedAngles2.begin(), sortedAngles2.end());
Toshihiro Shimizu 890ddd
							std::merge(sortedAngles1.begin(), sortedAngles1.end(), sortedAngles2.begin(), sortedAngles2.end(), sortedAngles.begin());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
							for (j = 0; j < sortedAngles.size(); j++) {
Toshihiro Shimizu 890ddd
								int numAng1 = angleNumber(angles1, sortedAngles[j]);
Toshihiro Shimizu 890ddd
								int numAng2 = angleNumber(angles2, sortedAngles[j]);
Toshihiro Shimizu 890ddd
								double val = (numAng1 == numAng2) ? 0 : fabs((float)(numAng1 - numAng2)) / (numAng1 + numAng2);
Toshihiro Shimizu 890ddd
								if (val < bestValue) {
Toshihiro Shimizu 890ddd
									bestValue = val;
Toshihiro Shimizu 890ddd
									bestAngle = (int)(sortedAngles[j]);
Toshihiro Shimizu 890ddd
									if (bestValue == 0 || !isTooComplex(numAng1, numAng2, maxSubSetNum))
Toshihiro Shimizu 890ddd
										break;
Toshihiro Shimizu 890ddd
								}
Toshihiro Shimizu 890ddd
							}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
						} else //-----------------------------------------------------
Toshihiro Shimizu 890ddd
						{
Toshihiro Shimizu 890ddd
							for (int angle = firstAngle; angle <= lastAngle; angle++) {
Toshihiro Shimizu 890ddd
								int numAng1 = angleNumber(angles1, angle);
Toshihiro Shimizu 890ddd
								int numAng2 = angleNumber(angles2, angle);
Toshihiro Shimizu 890ddd
								double val = (numAng1 == numAng2) ? 0 : fabs((float)(numAng1 - numAng2)) / (numAng1 + numAng2);
Toshihiro Shimizu 890ddd
								if (val < bestValue) {
Toshihiro Shimizu 890ddd
									bestValue = val;
Toshihiro Shimizu 890ddd
									bestAngle = angle;
Toshihiro Shimizu 890ddd
									if (bestValue == 0 || !isTooComplex(numAng1, numAng2, maxSubSetNum))
Toshihiro Shimizu 890ddd
										break;
Toshihiro Shimizu 890ddd
								}
Toshihiro Shimizu 890ddd
							}
Toshihiro Shimizu 890ddd
						}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
						eraseSmallAngles(angles1, bestAngle);
Toshihiro Shimizu 890ddd
						eraseSmallAngles(angles2, bestAngle);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
						/*
Toshihiro Shimizu 890ddd
            debugStream <<"bestAngle: "<< bestAngle << endl;
Toshihiro Shimizu 890ddd
            debugStream <<"num angoli 1: "<< angles1.size() << endl;
Toshihiro Shimizu 890ddd
            debugStream <<"num angoli 2: "<< angles2.size() << endl;
Toshihiro Shimizu 890ddd
            */
Toshihiro Shimizu 890ddd
					}
Toshihiro Shimizu 890ddd
					//--------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					bestValue = (std::numeric_limits<double>::max)();</double>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					if (angles1.size() == angles2.size()) {
Toshihiro Shimizu 890ddd
						transform.m_firstStrokeCornerIndexes.push_back(0);
Toshihiro Shimizu 890ddd
						for (j = 0; j < angles1.size(); j++)
Toshihiro Shimizu 890ddd
							transform.m_firstStrokeCornerIndexes.push_back(angles1[j].first);
Toshihiro Shimizu 890ddd
						transform.m_firstStrokeCornerIndexes.push_back(stroke1->getChunkCount());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
						transform.m_secondStrokeCornerIndexes.push_back(0);
Toshihiro Shimizu 890ddd
						for (j = 0; j < angles2.size(); j++)
Toshihiro Shimizu 890ddd
							transform.m_secondStrokeCornerIndexes.push_back(angles2[j].first);
Toshihiro Shimizu 890ddd
						transform.m_secondStrokeCornerIndexes.push_back(stroke2->getChunkCount());
Toshihiro Shimizu 890ddd
					} else {
Toshihiro Shimizu 890ddd
						if (isTooComplex(angles1.size(), angles2.size(), maxSubSetNum)) {
Toshihiro Shimizu 890ddd
							if (angles1.size() > angles2.size()) {
Toshihiro Shimizu 890ddd
								transform.m_firstStrokeCornerIndexes.resize(angles2.size());
Toshihiro Shimizu 890ddd
								trivialSolution(stroke1, stroke2, angles1, angles2, transform.m_firstStrokeCornerIndexes);
Toshihiro Shimizu 890ddd
								transform.m_firstStrokeCornerIndexes.insert(transform.m_firstStrokeCornerIndexes.begin(), 0);
Toshihiro Shimizu 890ddd
								transform.m_firstStrokeCornerIndexes.push_back(stroke1->getChunkCount());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
								transform.m_secondStrokeCornerIndexes.push_back(0);
Toshihiro Shimizu 890ddd
								for (j = 0; j < angles2.size(); j++)
Toshihiro Shimizu 890ddd
									transform.m_secondStrokeCornerIndexes.push_back(angles2[j].first);
Toshihiro Shimizu 890ddd
								transform.m_secondStrokeCornerIndexes.push_back(stroke2->getChunkCount());
Toshihiro Shimizu 890ddd
							} else {
Toshihiro Shimizu 890ddd
								transform.m_firstStrokeCornerIndexes.push_back(0);
Toshihiro Shimizu 890ddd
								for (j = 0; j < angles1.size(); j++)
Toshihiro Shimizu 890ddd
									transform.m_firstStrokeCornerIndexes.push_back(angles1[j].first);
Toshihiro Shimizu 890ddd
								transform.m_firstStrokeCornerIndexes.push_back(stroke1->getChunkCount());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
								transform.m_secondStrokeCornerIndexes.resize(angles1.size());
Toshihiro Shimizu 890ddd
								trivialSolution(stroke2, stroke1, angles2, angles1, transform.m_secondStrokeCornerIndexes);
Toshihiro Shimizu 890ddd
								transform.m_secondStrokeCornerIndexes.insert(transform.m_secondStrokeCornerIndexes.begin(), 0);
Toshihiro Shimizu 890ddd
								transform.m_secondStrokeCornerIndexes.push_back(stroke2->getChunkCount());
Toshihiro Shimizu 890ddd
							}
Toshihiro Shimizu 890ddd
						} else {
Toshihiro Shimizu 890ddd
							if (angles1.size() > angles2.size()) {
Toshihiro Shimizu 890ddd
								transform.m_firstStrokeCornerIndexes.resize(angles2.size());
Toshihiro Shimizu 890ddd
								findBestSolution(stroke1, stroke2, angles1, angles2, bestValue, transform.m_firstStrokeCornerIndexes);
Toshihiro Shimizu 890ddd
								transform.m_firstStrokeCornerIndexes.insert(transform.m_firstStrokeCornerIndexes.begin(), 0);
Toshihiro Shimizu 890ddd
								transform.m_firstStrokeCornerIndexes.push_back(stroke1->getChunkCount());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
								transform.m_secondStrokeCornerIndexes.push_back(0);
Toshihiro Shimizu 890ddd
								for (j = 0; j < angles2.size(); j++)
Toshihiro Shimizu 890ddd
									transform.m_secondStrokeCornerIndexes.push_back(angles2[j].first);
Toshihiro Shimizu 890ddd
								transform.m_secondStrokeCornerIndexes.push_back(stroke2->getChunkCount());
Toshihiro Shimizu 890ddd
							} else {
Toshihiro Shimizu 890ddd
								transform.m_firstStrokeCornerIndexes.push_back(0);
Toshihiro Shimizu 890ddd
								for (j = 0; j < angles1.size(); j++)
Toshihiro Shimizu 890ddd
									transform.m_firstStrokeCornerIndexes.push_back(angles1[j].first);
Toshihiro Shimizu 890ddd
								transform.m_firstStrokeCornerIndexes.push_back(stroke1->getChunkCount());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
								transform.m_secondStrokeCornerIndexes.resize(angles1.size());
Toshihiro Shimizu 890ddd
								findBestSolution(stroke2, stroke1, angles2, angles1, bestValue, transform.m_secondStrokeCornerIndexes);
Toshihiro Shimizu 890ddd
								transform.m_secondStrokeCornerIndexes.insert(transform.m_secondStrokeCornerIndexes.begin(), 0);
Toshihiro Shimizu 890ddd
								transform.m_secondStrokeCornerIndexes.push_back(stroke2->getChunkCount());
Toshihiro Shimizu 890ddd
							}
Toshihiro Shimizu 890ddd
						}
Toshihiro Shimizu 890ddd
					}
Toshihiro Shimizu 890ddd
				} else {
Toshihiro Shimizu 890ddd
					transform.m_firstStrokeCornerIndexes.push_back(0);
Toshihiro Shimizu 890ddd
					for (j = 0; j < angles1.size(); j++)
Toshihiro Shimizu 890ddd
						transform.m_firstStrokeCornerIndexes.push_back(angles1[j].first);
Toshihiro Shimizu 890ddd
					transform.m_firstStrokeCornerIndexes.push_back(stroke1->getChunkCount());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					transform.m_secondStrokeCornerIndexes.push_back(0);
Toshihiro Shimizu 890ddd
					for (j = 0; j < angles2.size(); j++)
Toshihiro Shimizu 890ddd
						transform.m_secondStrokeCornerIndexes.push_back(angles2[j].first);
Toshihiro Shimizu 890ddd
					transform.m_secondStrokeCornerIndexes.push_back(stroke2->getChunkCount());
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				UINT cornerSize = transform.m_firstStrokeCornerIndexes.size();
Toshihiro Shimizu 890ddd
				assert(cornerSize == transform.m_secondStrokeCornerIndexes.size());
Toshihiro Shimizu 890ddd
				assert(cornerSize >= 2);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				double totalRadRotation = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				TStroke *subStroke1 = 0;
Toshihiro Shimizu 890ddd
				TStroke *subStroke2 = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				stroke1Centroid = stroke1->getCentroid();
Toshihiro Shimizu 890ddd
				stroke2Centroid = stroke2->getCentroid();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef _DEBUG
Toshihiro Shimizu 890ddd
				assert(transform.m_firstStrokeCornerIndexes[0] == 0);
Toshihiro Shimizu 890ddd
				assert(transform.m_secondStrokeCornerIndexes[0] == 0);
Toshihiro Shimizu 890ddd
				assert(transform.m_firstStrokeCornerIndexes[cornerSize - 1] == stroke1->getChunkCount());
Toshihiro Shimizu 890ddd
				assert(transform.m_secondStrokeCornerIndexes[cornerSize - 1] == stroke2->getChunkCount());
Toshihiro Shimizu 890ddd
				for (j = 0; j < cornerSize - 1; j++) {
Toshihiro Shimizu 890ddd
					assert(transform.m_firstStrokeCornerIndexes[j] < transform.m_firstStrokeCornerIndexes[j + 1]);
Toshihiro Shimizu 890ddd
					assert(transform.m_secondStrokeCornerIndexes[j] < transform.m_secondStrokeCornerIndexes[j + 1]);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					assert(transform.m_firstStrokeCornerIndexes[j] < stroke1->getChunkCount());
Toshihiro Shimizu 890ddd
					assert(transform.m_secondStrokeCornerIndexes[j] < stroke2->getChunkCount());
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				for (j = 0; j < cornerSize - 1; j++) {
Toshihiro Shimizu 890ddd
					///////////////////////////////////////// sampling
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					subStroke1 = extract(stroke1, transform.m_firstStrokeCornerIndexes[j], transform.m_firstStrokeCornerIndexes[j + 1] - 1);
Toshihiro Shimizu 890ddd
					sample(subStroke1, samplingPointNumber, samplingPoint1);
Toshihiro Shimizu 890ddd
					subStroke2 = extract(stroke2, transform.m_secondStrokeCornerIndexes[j], transform.m_secondStrokeCornerIndexes[j + 1] - 1);
Toshihiro Shimizu 890ddd
					sample(subStroke2, samplingPointNumber, samplingPoint2);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					///////////////////////////////////////// compute Rotation
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					ratioSampling.clear();
Toshihiro Shimizu 890ddd
					ratioSampling.reserve(samplingPointNumber);
Toshihiro Shimizu 890ddd
					weigths.clear();
Toshihiro Shimizu 890ddd
					weigths.reserve(samplingPointNumber);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					TPointD pOld, pNew;
Toshihiro Shimizu 890ddd
					// double totalW=0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					for (p = 0; p < samplingPointNumber; p++) {
Toshihiro Shimizu 890ddd
						pOld = samplingPoint1[p];
Toshihiro Shimizu 890ddd
						pNew = samplingPoint2[p];
Toshihiro Shimizu 890ddd
						if (pOld == stroke1Centroid)
Toshihiro Shimizu 890ddd
							continue;
Toshihiro Shimizu 890ddd
						if (pNew == stroke2Centroid)
Toshihiro Shimizu 890ddd
							continue;
Toshihiro Shimizu 890ddd
						versor1 = normalize(pOld - stroke1Centroid);
Toshihiro Shimizu 890ddd
						versor2 = normalize(pNew - stroke2Centroid);
Toshihiro Shimizu 890ddd
						weigths.push_back(tdistance(pOld, stroke1Centroid) + tdistance(pNew, stroke2Centroid));
Toshihiro Shimizu 890ddd
						cs = versor1 * versor2;
Toshihiro Shimizu 890ddd
						sn = cross(versor1, versor2);
Toshihiro Shimizu 890ddd
						double v = atan2(sn, cs);
Toshihiro Shimizu 890ddd
						ratioSampling.push_back(v);
Toshihiro Shimizu 890ddd
					}
Toshihiro Shimizu 890ddd
					delete subStroke1;
Toshihiro Shimizu 890ddd
					delete subStroke2;
Toshihiro Shimizu 890ddd
					subStroke1 = 0;
Toshihiro Shimizu 890ddd
					subStroke2 = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					double radRotation = weightedAverage(ratioSampling, weigths);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					totalRadRotation += radRotation;
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
				totalRadRotation /= (cornerSize - 1);
Toshihiro Shimizu 890ddd
				transform.m_rotation = TConsts::invOf_pi_180 * totalRadRotation;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				if (isAlmostZero(transform.m_rotation, 2)) {
Toshihiro Shimizu 890ddd
					transform.m_rotation = 0.0;
Toshihiro Shimizu 890ddd
					totalRadRotation = 0.0;
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef _DEBUG
Toshihiro Shimizu 890ddd
//        TDebugMessage::getStream()<<"rotation "<< transform.m_rotation;
Toshihiro Shimizu 890ddd
//        TDebugMessage::flush();
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				///////////////////////////////////////// compute Scale
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				if (transform.m_rotation == 0.0) {
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					subStrokeXScaling.clear();
Toshihiro Shimizu 890ddd
					subStrokeXScaling.reserve(cornerSize - 1);
Toshihiro Shimizu 890ddd
					subStrokeYScaling.clear();
Toshihiro Shimizu 890ddd
					subStrokeYScaling.reserve(cornerSize - 1);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					for (j = 0; j < cornerSize - 1; j++) {
Toshihiro Shimizu 890ddd
						///////////////////////////////////////// sampling
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
						subStroke1 = extract(stroke1, transform.m_firstStrokeCornerIndexes[j], transform.m_firstStrokeCornerIndexes[j + 1] - 1);
Toshihiro Shimizu 890ddd
						sample(subStroke1, samplingPointNumber, samplingPoint1);
Toshihiro Shimizu 890ddd
						subStroke2 = extract(stroke2, transform.m_secondStrokeCornerIndexes[j], transform.m_secondStrokeCornerIndexes[j + 1] - 1);
Toshihiro Shimizu 890ddd
						sample(subStroke2, samplingPointNumber, samplingPoint2);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
						///////////////////////////////////////// compute X Scale
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
						ratioSampling.clear();
Toshihiro Shimizu 890ddd
						ratioSampling.reserve(samplingPointNumber + bboxSamplingWeight);
Toshihiro Shimizu 890ddd
						double appX, appY;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
						TPointD appPoint;
Toshihiro Shimizu 890ddd
						double bboxXMin, bboxYMin, bboxXMax, bboxYMax;
Toshihiro Shimizu 890ddd
						bboxXMin = bboxYMin = (std::numeric_limits<double>::max)();</double>
Toshihiro Shimizu 890ddd
						bboxXMax = bboxYMax = -(std::numeric_limits<double>::max)();</double>
Toshihiro Shimizu 890ddd
						int h;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
						for (h = 0; h < subStroke1->getControlPointCount(); ++h) {
Toshihiro Shimizu 890ddd
							appPoint = subStroke1->getControlPoint(h);
Toshihiro Shimizu 890ddd
							if (appPoint.x < bboxXMin)
Toshihiro Shimizu 890ddd
								bboxXMin = appPoint.x;
Toshihiro Shimizu 890ddd
							if (appPoint.x > bboxXMax)
Toshihiro Shimizu 890ddd
								bboxXMax = appPoint.x;
Toshihiro Shimizu 890ddd
							if (appPoint.y < bboxYMin)
Toshihiro Shimizu 890ddd
								bboxYMin = appPoint.y;
Toshihiro Shimizu 890ddd
							if (appPoint.y > bboxYMax)
Toshihiro Shimizu 890ddd
								bboxYMax = appPoint.y;
Toshihiro Shimizu 890ddd
						}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
						appX = bboxXMax - bboxXMin;
Toshihiro Shimizu 890ddd
						appY = bboxYMax - bboxYMin;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
						if (appX) {
Toshihiro Shimizu 890ddd
							bboxXMin = (std::numeric_limits<double>::max)();</double>
Toshihiro Shimizu 890ddd
							bboxXMax = -(std::numeric_limits<double>::max)();</double>
Toshihiro Shimizu 890ddd
							for (h = 0; h < subStroke2->getControlPointCount(); ++h) {
Toshihiro Shimizu 890ddd
								appPoint = subStroke2->getControlPoint(h);
Toshihiro Shimizu 890ddd
								if (appPoint.x < bboxXMin)
Toshihiro Shimizu 890ddd
									bboxXMin = appPoint.x;
Toshihiro Shimizu 890ddd
								if (appPoint.x > bboxXMax)
Toshihiro Shimizu 890ddd
									bboxXMax = appPoint.x;
Toshihiro Shimizu 890ddd
							}
Toshihiro Shimizu 890ddd
							appX = (isAlmostZero(appX, 1e-01)) ? -1 : (bboxXMax - bboxXMin) / appX;
Toshihiro Shimizu 890ddd
							for (UINT tms = 0; tms < bboxSamplingWeight && appX >= 0; tms++)
Toshihiro Shimizu 890ddd
								ratioSampling.push_back(appX);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
							for (p = 0; p < samplingPointNumber; p++) {
Toshihiro Shimizu 890ddd
								appX = fabs(samplingPoint1[p].x - stroke1Centroid.x);
Toshihiro Shimizu 890ddd
								if (appX)
Toshihiro Shimizu 890ddd
									ratioSampling.push_back(fabs(samplingPoint2[p].x - stroke2Centroid.x) / appX);
Toshihiro Shimizu 890ddd
							}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
							if (!ratioSampling.empty()) {
Toshihiro Shimizu 890ddd
								subStrokeXScaling.push_back(average(ratioSampling));
Toshihiro Shimizu 890ddd
							}
Toshihiro Shimizu 890ddd
						}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
						///////////////////////////////////////// compute Y Scale
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
						ratioSampling.clear();
Toshihiro Shimizu 890ddd
						ratioSampling.reserve(samplingPointNumber + bboxSamplingWeight);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
						if (appY) {
Toshihiro Shimizu 890ddd
							bboxYMin = (std::numeric_limits<double>::max)();</double>
Toshihiro Shimizu 890ddd
							bboxYMax = -(std::numeric_limits<double>::max)();</double>
Toshihiro Shimizu 890ddd
							for (h = 0; h < subStroke2->getControlPointCount(); ++h) {
Toshihiro Shimizu 890ddd
								appPoint = subStroke2->getControlPoint(h);
Toshihiro Shimizu 890ddd
								if (appPoint.y < bboxYMin)
Toshihiro Shimizu 890ddd
									bboxYMin = appPoint.y;
Toshihiro Shimizu 890ddd
								if (appPoint.y > bboxYMax)
Toshihiro Shimizu 890ddd
									bboxYMax = appPoint.y;
Toshihiro Shimizu 890ddd
							}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
							appY = (isAlmostZero(appY, 1e-01)) ? -1 : (bboxYMax - bboxYMin) / appY;
Toshihiro Shimizu 890ddd
							for (UINT tms = 0; tms < bboxSamplingWeight && appY >= 0; tms++)
Toshihiro Shimizu 890ddd
								ratioSampling.push_back(appY);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
							for (p = 0; p < samplingPointNumber; p++) {
Toshihiro Shimizu 890ddd
								appY = fabs(samplingPoint1[p].y - stroke1Centroid.y);
Toshihiro Shimizu 890ddd
								if (appY)
Toshihiro Shimizu 890ddd
									ratioSampling.push_back(fabs(samplingPoint2[p].y - stroke2Centroid.y) / appY);
Toshihiro Shimizu 890ddd
							}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
							if (!ratioSampling.empty()) {
Toshihiro Shimizu 890ddd
								subStrokeYScaling.push_back(average(ratioSampling));
Toshihiro Shimizu 890ddd
							}
Toshihiro Shimizu 890ddd
						}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
						delete subStroke1;
Toshihiro Shimizu 890ddd
						delete subStroke2;
Toshihiro Shimizu 890ddd
						subStroke1 = 0;
Toshihiro Shimizu 890ddd
						subStroke2 = 0;
Toshihiro Shimizu 890ddd
					}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					if (subStrokeXScaling.empty()) {
Toshihiro Shimizu 890ddd
						transform.m_scaleX = 1.0;
Toshihiro Shimizu 890ddd
					} else {
Toshihiro Shimizu 890ddd
						transform.m_scaleX = average(subStrokeXScaling);
Toshihiro Shimizu 890ddd
						if (isAlmostZero(transform.m_scaleX - 1.0))
Toshihiro Shimizu 890ddd
							transform.m_scaleX = 1.0;
Toshihiro Shimizu 890ddd
					}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					if (subStrokeYScaling.empty()) {
Toshihiro Shimizu 890ddd
						transform.m_scaleY = 1.0;
Toshihiro Shimizu 890ddd
					} else {
Toshihiro Shimizu 890ddd
						transform.m_scaleY = average(subStrokeYScaling);
Toshihiro Shimizu 890ddd
						if (isAlmostZero(transform.m_scaleY - 1.0))
Toshihiro Shimizu 890ddd
							transform.m_scaleY = 1.0;
Toshihiro Shimizu 890ddd
					}
Toshihiro Shimizu 890ddd
					/*
Toshihiro Shimizu 890ddd
         #ifdef _DEBUG
Toshihiro Shimizu 890ddd
              
Toshihiro Shimizu 890ddd
          TDebugMessage::getStream()<<"x scale "<< transform.m_scaleX ;
Toshihiro Shimizu 890ddd
          TDebugMessage::flush();
Toshihiro Shimizu 890ddd
          TDebugMessage::getStream()<<"y scale "<< transform.m_scaleY ;
Toshihiro Shimizu 890ddd
          TDebugMessage::flush();
Toshihiro Shimizu 890ddd
        #endif
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
				} else {
Toshihiro Shimizu 890ddd
					subStrokeXScaling.clear();
Toshihiro Shimizu 890ddd
					subStrokeXScaling.reserve(cornerSize - 1);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					for (j = 0; j < cornerSize - 1; j++) {
Toshihiro Shimizu 890ddd
						///////////////////////////////////////// sampling
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
						subStroke1 = extract(stroke1, transform.m_firstStrokeCornerIndexes[j], transform.m_firstStrokeCornerIndexes[j + 1] - 1);
Toshihiro Shimizu 890ddd
						sample(subStroke1, samplingPointNumber, samplingPoint1);
Toshihiro Shimizu 890ddd
						subStroke2 = extract(stroke2, transform.m_secondStrokeCornerIndexes[j], transform.m_secondStrokeCornerIndexes[j + 1] - 1);
Toshihiro Shimizu 890ddd
						sample(subStroke2, samplingPointNumber, samplingPoint2);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
						///////////////////////////////////////// compute Scale
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
						ratioSampling.clear();
Toshihiro Shimizu 890ddd
						ratioSampling.reserve(samplingPointNumber + bboxSamplingWeight);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
						TRectD bbox1 = subStroke1->getBBox();
Toshihiro Shimizu 890ddd
						double app = tdistance2(bbox1.getP00(), bbox1.getP11());
Toshihiro Shimizu 890ddd
						if (app) {
Toshihiro Shimizu 890ddd
							TRectD bbox2 = TRotation(transform.m_rotation).inv() * subStroke2->getBBox();
Toshihiro Shimizu 890ddd
							app = sqrt(tdistance2(bbox2.getP00(), bbox2.getP11()) / app);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
							for (UINT tms = 0; tms < bboxSamplingWeight; tms++)
Toshihiro Shimizu 890ddd
								ratioSampling.push_back(app);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
							double app;
Toshihiro Shimizu 890ddd
							for (p = 0; p < samplingPointNumber; p++) {
Toshihiro Shimizu 890ddd
								app = tdistance(samplingPoint1[p], stroke1Centroid);
Toshihiro Shimizu 890ddd
								if (app) {
Toshihiro Shimizu 890ddd
									ratioSampling.push_back(tdistance(samplingPoint2[p], stroke2Centroid) / app);
Toshihiro Shimizu 890ddd
								}
Toshihiro Shimizu 890ddd
							}
Toshihiro Shimizu 890ddd
						}
Toshihiro Shimizu 890ddd
						if (!ratioSampling.empty()) {
Toshihiro Shimizu 890ddd
							subStrokeXScaling.push_back(average(ratioSampling));
Toshihiro Shimizu 890ddd
						}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
						delete subStroke1;
Toshihiro Shimizu 890ddd
						delete subStroke2;
Toshihiro Shimizu 890ddd
						subStroke1 = 0;
Toshihiro Shimizu 890ddd
						subStroke2 = 0;
Toshihiro Shimizu 890ddd
					}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					if (subStrokeXScaling.empty()) {
Toshihiro Shimizu 890ddd
						transform.m_scaleX = transform.m_scaleY = 1.0;
Toshihiro Shimizu 890ddd
					} else {
Toshihiro Shimizu 890ddd
						transform.m_scaleX = transform.m_scaleY = average(subStrokeXScaling);
Toshihiro Shimizu 890ddd
						if (isAlmostZero(transform.m_scaleX - 1.0, 0.00001))
Toshihiro Shimizu 890ddd
							transform.m_scaleX = transform.m_scaleY = 1.0;
Toshihiro Shimizu 890ddd
					}
Toshihiro Shimizu 890ddd
					/*          
Toshihiro Shimizu 890ddd
         #ifdef _DEBUG
Toshihiro Shimizu 890ddd
              
Toshihiro Shimizu 890ddd
          TDebugMessage::getStream()<<"scale "<< transform.m_scaleX ;
Toshihiro Shimizu 890ddd
          TDebugMessage::flush();
Toshihiro Shimizu 890ddd
         #endif
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				///////////////////////////////////////// compute centre of Rotation and Scaling
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				vector<tpointd> vpOld(cornerSize), vpNew(cornerSize);</tpointd>
Toshihiro Shimizu 890ddd
				TPointD pOld, pNew;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				for (j = 0; j < cornerSize - 1; j++) {
Toshihiro Shimizu 890ddd
					vpOld[j] = stroke1->getChunk(transform.m_firstStrokeCornerIndexes[j])->getP0();
Toshihiro Shimizu 890ddd
					vpNew[j] = stroke2->getChunk(transform.m_secondStrokeCornerIndexes[j])->getP0();
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
				vpOld[j] = stroke1->getControlPoint(stroke1->getControlPointCount());
Toshihiro Shimizu 890ddd
				vpNew[j] = stroke2->getControlPoint(stroke2->getControlPointCount());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				if (transform.m_rotation == 0.0) {
Toshihiro Shimizu 890ddd
					if (transform.m_scaleX == 1.0 && transform.m_scaleY == 1.0) {
Toshihiro Shimizu 890ddd
						transform.m_translate = stroke2Centroid - stroke1Centroid;
Toshihiro Shimizu 890ddd
						transform.m_rotationAndScaleCenter = TPointD();
Toshihiro Shimizu 890ddd
					} else {
Toshihiro Shimizu 890ddd
						if (transform.m_scaleX == 1.0) {
Toshihiro Shimizu 890ddd
							transform.m_rotationAndScaleCenter.x = 0;
Toshihiro Shimizu 890ddd
							transform.m_translate.x = 0;
Toshihiro Shimizu 890ddd
							for (j = 0; j < cornerSize; j++) {
Toshihiro Shimizu 890ddd
								transform.m_translate.x += vpNew[j].x - vpOld[j].x;
Toshihiro Shimizu 890ddd
							}
Toshihiro Shimizu 890ddd
							transform.m_translate.x = transform.m_translate.x / cornerSize;
Toshihiro Shimizu 890ddd
						} else {
Toshihiro Shimizu 890ddd
							transform.m_rotationAndScaleCenter.x = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
							for (j = 0; j < cornerSize; j++) {
Toshihiro Shimizu 890ddd
								pOld = vpOld[j];
Toshihiro Shimizu 890ddd
								pNew = vpNew[j];
Toshihiro Shimizu 890ddd
								transform.m_rotationAndScaleCenter.x += (transform.m_scaleX * pOld.x - pNew.x) / (transform.m_scaleX - 1.0);
Toshihiro Shimizu 890ddd
							}
Toshihiro Shimizu 890ddd
							transform.m_rotationAndScaleCenter.x = transform.m_rotationAndScaleCenter.x / cornerSize;
Toshihiro Shimizu 890ddd
							transform.m_translate.x = 0;
Toshihiro Shimizu 890ddd
						}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
						if (transform.m_scaleY == 1.0) {
Toshihiro Shimizu 890ddd
							transform.m_rotationAndScaleCenter.y = 0;
Toshihiro Shimizu 890ddd
							transform.m_translate.y = 0;
Toshihiro Shimizu 890ddd
							for (j = 0; j < cornerSize; j++) {
Toshihiro Shimizu 890ddd
								transform.m_translate.y += vpNew[j].y - vpOld[j].y;
Toshihiro Shimizu 890ddd
							}
Toshihiro Shimizu 890ddd
							transform.m_translate.y = transform.m_translate.y / cornerSize;
Toshihiro Shimizu 890ddd
						} else {
Toshihiro Shimizu 890ddd
							transform.m_rotationAndScaleCenter.y = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
							for (j = 0; j < cornerSize; j++) {
Toshihiro Shimizu 890ddd
								pOld = vpOld[j];
Toshihiro Shimizu 890ddd
								pNew = vpNew[j];
Toshihiro Shimizu 890ddd
								transform.m_rotationAndScaleCenter.y += (transform.m_scaleY * pOld.y - pNew.y) / (transform.m_scaleY - 1.0);
Toshihiro Shimizu 890ddd
							}
Toshihiro Shimizu 890ddd
							transform.m_rotationAndScaleCenter.y = transform.m_rotationAndScaleCenter.y / cornerSize;
Toshihiro Shimizu 890ddd
							transform.m_translate.y = 0;
Toshihiro Shimizu 890ddd
						}
Toshihiro Shimizu 890ddd
					}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				} else {
Toshihiro Shimizu 890ddd
					assert(transform.m_scaleX = transform.m_scaleY);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					cs = transform.m_scaleX * cos(totalRadRotation);
Toshihiro Shimizu 890ddd
					sn = transform.m_scaleX * sin(totalRadRotation);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					// scelgo punti da usare come vincolo, per ottenere la translazione, dato un centro di rotazione
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					// dato il punto pOld e pNew si calcola analiticamnete il punto di rotazione e scala
Toshihiro Shimizu 890ddd
					// che minimizza la traslazione aggiuntiva e la traslazione stessa
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					for (j = 0; j < cornerSize; j++) {
Toshihiro Shimizu 890ddd
						pOld = vpOld[j];
Toshihiro Shimizu 890ddd
						pNew = vpNew[j];
Toshihiro Shimizu 890ddd
						constK = pNew.x - cs * pOld.x + sn * pOld.y;
Toshihiro Shimizu 890ddd
						constQ = pNew.y - sn * pOld.x - cs * pOld.y;
Toshihiro Shimizu 890ddd
						constB = 2 * (constK * (cs - 1.) + sn * constQ);
Toshihiro Shimizu 890ddd
						constD = 2 * (constQ * (cs - 1.) - sn * constK);
Toshihiro Shimizu 890ddd
						constA = transform.m_scaleX * transform.m_scaleX + 1 - 2 * cs;
Toshihiro Shimizu 890ddd
						assert(constA > 0);
Toshihiro Shimizu 890ddd
						constA = 1.0 / (2 * constA);
Toshihiro Shimizu 890ddd
						transform.m_rotationAndScaleCenter.x += -constB * constA;
Toshihiro Shimizu 890ddd
						transform.m_rotationAndScaleCenter.y += -constD * constA;
Toshihiro Shimizu 890ddd
					}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					transform.m_rotationAndScaleCenter = transform.m_rotationAndScaleCenter * (1.0 / (double)cornerSize);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					transform.m_translate.x = (cs - 1.0) * transform.m_rotationAndScaleCenter.x - sn * transform.m_rotationAndScaleCenter.y + constK;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					transform.m_translate.y = sn * transform.m_rotationAndScaleCenter.x + (cs - 1.0) * transform.m_rotationAndScaleCenter.y + constQ;
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				/////////////////////////////////////////
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				transform.m_inverse = (TTranslation(transform.m_translate) *
Toshihiro Shimizu 890ddd
									   TScale(transform.m_rotationAndScaleCenter, transform.m_scaleX, transform.m_scaleY) *
Toshihiro Shimizu 890ddd
									   TRotation(transform.m_rotationAndScaleCenter, transform.m_rotation))
Toshihiro Shimizu 890ddd
										  .inv();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				//debugStream.close();
Toshihiro Shimizu 890ddd
			} // end if !isPoint
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		} // end if !isEqual
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		m_transformation.push_back(transform);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	} // end for each stroke
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TVectorImageP TInbetween::Imp::tween(double t) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	const double step = 5.0;
Toshihiro Shimizu 890ddd
	const double interpolateError = 1.0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TVectorImageP vi = new TVectorImage;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	UINT strokeCount1 = m_firstImage->getStrokeCount();
Toshihiro Shimizu 890ddd
	UINT strokeCount2 = m_lastImage->getStrokeCount();
Toshihiro Shimizu 890ddd
	vi->setPalette(m_firstImage->getPalette());
Toshihiro Shimizu 890ddd
	if (strokeCount1 > strokeCount2)
Toshihiro Shimizu 890ddd
		strokeCount1 = strokeCount2;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	assert(m_transformation.size() == strokeCount1);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double totalLen1, totalLen2, len1, len2, step1, step2;
Toshihiro Shimizu 890ddd
	vector<tthickpoint> points;</tthickpoint>
Toshihiro Shimizu 890ddd
	TStroke *stroke1, *stroke2, *subStroke1, *subStroke2, *stroke;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TAffine mt, invMatrix;
Toshihiro Shimizu 890ddd
	TThickPoint point2, finalPoint;
Toshihiro Shimizu 890ddd
	UINT i, j, cp, cpSize;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (i = 0; i < strokeCount1; i++) {
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		stroke1 = m_firstImage->getStroke(i);
Toshihiro Shimizu 890ddd
		stroke2 = m_lastImage->getStroke(i);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (m_transformation[i].m_type == StrokeTransform::EQUAL) {
Toshihiro Shimizu 890ddd
			stroke = new TStroke(*stroke1);
Toshihiro Shimizu 890ddd
		} else {
Toshihiro Shimizu 890ddd
			points.clear();
Toshihiro Shimizu 890ddd
			totalLen1 = stroke1->getLength();
Toshihiro Shimizu 890ddd
			totalLen2 = stroke2->getLength();
Toshihiro Shimizu 890ddd
			;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			if (stroke1->getControlPointCount() == stroke2->getControlPointCount() &&
Toshihiro Shimizu 890ddd
				stroke1->isSelfLoop() && stroke2->isSelfLoop()) {
Toshihiro Shimizu 890ddd
				for (int i = 0; i < stroke1->getControlPointCount(); i++) {
Toshihiro Shimizu 890ddd
					TThickPoint p0 = stroke1->getControlPoint(i);
Toshihiro Shimizu 890ddd
					TThickPoint p1 = stroke2->getControlPoint(i);
Toshihiro Shimizu 890ddd
					points.push_back(p0 * (1 - t) + p1 * t);
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
				stroke = new TStroke(points);
Toshihiro Shimizu 890ddd
			} else if (m_transformation[i].m_type == StrokeTransform::POINT) {
Toshihiro Shimizu 890ddd
				TThickPoint pOld = stroke1->getThickPointAtLength(0.5 * totalLen1);
Toshihiro Shimizu 890ddd
				TThickPoint pNew = stroke2->getThickPointAtLength(0.5 * totalLen2);
Toshihiro Shimizu 890ddd
				points.push_back(pOld * (1 - t) + pNew * t);
Toshihiro Shimizu 890ddd
				points.push_back(points[0]);
Toshihiro Shimizu 890ddd
				points.push_back(points[0]);
Toshihiro Shimizu 890ddd
				stroke = new TStroke(points);
Toshihiro Shimizu 890ddd
			} else {
Toshihiro Shimizu 890ddd
				mt = (m_transformation[i].m_inverse.isIdentity())
Toshihiro Shimizu 890ddd
						 ? TAffine()
Toshihiro Shimizu 890ddd
						 : TTranslation(m_transformation[i].m_translate * t) *
Toshihiro Shimizu 890ddd
							   TScale(m_transformation[i].m_rotationAndScaleCenter, (1 - t) + t * m_transformation[i].m_scaleX, (1 - t) + t * m_transformation[i].m_scaleY) *
Toshihiro Shimizu 890ddd
							   TRotation(m_transformation[i].m_rotationAndScaleCenter, m_transformation[i].m_rotation * t);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				UINT cornerSize = m_transformation[i].m_firstStrokeCornerIndexes.size();
Toshihiro Shimizu 890ddd
				assert(cornerSize == m_transformation[i].m_secondStrokeCornerIndexes.size());
Toshihiro Shimizu 890ddd
				if (cornerSize > m_transformation[i].m_secondStrokeCornerIndexes.size())
Toshihiro Shimizu 890ddd
					cornerSize = m_transformation[i].m_secondStrokeCornerIndexes.size();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				assert(cornerSize >= 2);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				std::vector<tthickpoint> controlPoints;</tthickpoint>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				//if not m_transformation[i].m_findCorners => detect corner return different size =>cornerSize==2
Toshihiro Shimizu 890ddd
				// assert(!m_transformation[i].m_findCorners || cornerSize==2);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				for (j = 0; j < cornerSize - 1; j++) {
Toshihiro Shimizu 890ddd
					points.clear();
Toshihiro Shimizu 890ddd
					subStroke1 = extract(stroke1, m_transformation[i].m_firstStrokeCornerIndexes[j], m_transformation[i].m_firstStrokeCornerIndexes[j + 1] - 1);
Toshihiro Shimizu 890ddd
					subStroke2 = extract(stroke2, m_transformation[i].m_secondStrokeCornerIndexes[j], m_transformation[i].m_secondStrokeCornerIndexes[j + 1] - 1);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					totalLen1 = subStroke1->getLength();
Toshihiro Shimizu 890ddd
					totalLen2 = subStroke2->getLength();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					if (totalLen1 > totalLen2) {
Toshihiro Shimizu 890ddd
						step1 = step;
Toshihiro Shimizu 890ddd
						step2 = (totalLen2 / totalLen1) * step;
Toshihiro Shimizu 890ddd
					} else {
Toshihiro Shimizu 890ddd
						step1 = (totalLen1 / totalLen2) * step;
Toshihiro Shimizu 890ddd
						step2 = step;
Toshihiro Shimizu 890ddd
					}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					len1 = 0;
Toshihiro Shimizu 890ddd
					len2 = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					while (len1 <= totalLen1 && len2 <= totalLen2) {
Toshihiro Shimizu 890ddd
						point2 = subStroke2->getThickPointAtLength(len2);
Toshihiro Shimizu 890ddd
						point2 = TThickPoint(m_transformation[i].m_inverse * subStroke2->getThickPointAtLength(len2), point2.thick);
Toshihiro Shimizu 890ddd
						finalPoint = subStroke1->getThickPointAtLength(len1) * (1 - t) + t * point2;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
						points.push_back(TThickPoint(mt * (finalPoint), finalPoint.thick));
Toshihiro Shimizu 890ddd
						len1 += step1;
Toshihiro Shimizu 890ddd
						len2 += step2;
Toshihiro Shimizu 890ddd
					}
Toshihiro Shimizu 890ddd
					point2 = subStroke2->getThickPointAtLength(totalLen2);
Toshihiro Shimizu 890ddd
					point2 = TThickPoint(m_transformation[i].m_inverse * subStroke2->getThickPointAtLength(totalLen2), point2.thick);
Toshihiro Shimizu 890ddd
					finalPoint = subStroke1->getThickPointAtLength(totalLen1) * (1 - t) + t * point2;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					points.push_back(TThickPoint(mt * (finalPoint), finalPoint.thick));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					stroke = TStroke::interpolate(points, interpolateError, false
Toshihiro Shimizu 890ddd
												  /*m_transformation[i].m_findCorners*/);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					if (j == 0)
Toshihiro Shimizu 890ddd
						controlPoints.push_back(stroke->getControlPoint(0));
Toshihiro Shimizu 890ddd
					else
Toshihiro Shimizu 890ddd
						controlPoints.back() = (controlPoints.back() + stroke->getControlPoint(0)) * 0.5;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					cpSize = stroke->getControlPointCount();
Toshihiro Shimizu 890ddd
					for (cp = 1; cp < cpSize; cp++) {
Toshihiro Shimizu 890ddd
						controlPoints.push_back(stroke->getControlPoint(cp));
Toshihiro Shimizu 890ddd
					}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					delete subStroke1;
Toshihiro Shimizu 890ddd
					delete subStroke2;
Toshihiro Shimizu 890ddd
					delete stroke;
Toshihiro Shimizu 890ddd
					subStroke1 = 0;
Toshihiro Shimizu 890ddd
					subStroke2 = 0;
Toshihiro Shimizu 890ddd
					stroke = 0;
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				stroke = new TStroke(controlPoints);
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (stroke1->isSelfLoop() && stroke2->isSelfLoop())
Toshihiro Shimizu 890ddd
			stroke->setSelfLoop();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		stroke->setStyle(stroke1->getStyle());
Toshihiro Shimizu 890ddd
		stroke->outlineOptions() = stroke1->outlineOptions();
Toshihiro Shimizu 890ddd
		VIStroke *vs = new VIStroke(stroke, m_firstImage->getVIStroke(i)->m_groupId);
Toshihiro Shimizu 890ddd
		vi->m_imp->m_strokes.push_back(vs);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	} //end for each stroke
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (m_firstImage->isComputedRegionAlmostOnce())
Toshihiro Shimizu 890ddd
		transferColor(vi);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return vi;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TInbetween::Imp::transferColor(const TVectorImageP &destination) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	const TVectorImageP &original = m_firstImage;
Toshihiro Shimizu 890ddd
	destination->setPalette(original->getPalette());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	destination->findRegions();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (destination->getRegionCount()) {
Toshihiro Shimizu 890ddd
		UINT strokeCount1 = original->getStrokeCount();
Toshihiro Shimizu 890ddd
		UINT strokeCount2 = destination->getStrokeCount();
Toshihiro Shimizu 890ddd
		if (strokeCount1 > strokeCount2)
Toshihiro Shimizu 890ddd
			strokeCount1 = strokeCount2;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		for (UINT i = 0; i < strokeCount1; i++) {
Toshihiro Shimizu 890ddd
			TVectorImage::transferStrokeColors(original, i, destination, i);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TVectorImageP TInbetween::tween(double t) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return m_imp->tween(t);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------