Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "tmachine.h"
Toshihiro Shimizu 890ddd
#include "tmathutil.h"
Toshihiro Shimizu 890ddd
#include "tstrokeutil.h"
Toshihiro Shimizu 890ddd
#include "tstrokeoutline.h"
Toshihiro Shimizu 890ddd
#include "tcurves.h"
Toshihiro Shimizu 890ddd
#include "tbezier.h"
Toshihiro Shimizu 890ddd
#include "tzerofinder.h"
Toshihiro Shimizu 890ddd
#include "tcurveutil.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include <limits></limits>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "tstroke.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#define USE_NEW_3D_ERROR_COMPUTE 1
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// Some using declaration
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
using namespace TConsts;
Toshihiro Shimizu 890ddd
using namespace std;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// Some useful typedefs
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
typedef std::vector<double> DoubleArray;</double>
Toshihiro Shimizu 890ddd
typedef DoubleArray::iterator DoubleIt;
Toshihiro Shimizu 890ddd
typedef std::vector<tthickquadratic *=""> QuadStrokeChunkArray;</tthickquadratic>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
static int numSaved = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void detectCorners(const std::vector<t3dpointd> &points,</t3dpointd>
Toshihiro Shimizu 890ddd
				   int minSampleNum,
Toshihiro Shimizu 890ddd
				   int minDist,
Toshihiro Shimizu 890ddd
				   int maxDist,
Toshihiro Shimizu 890ddd
				   double maxAngle,
Toshihiro Shimizu 890ddd
				   std::vector<int> &corners);</int>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
namespace
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void extractStrokeControlPoints(const QuadStrokeChunkArray &curves,
Toshihiro Shimizu 890ddd
								vector<tthickpoint> &ctrlPnts)</tthickpoint>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	const TThickQuadratic *prev = curves[0];
Toshihiro Shimizu 890ddd
	assert(prev);
Toshihiro Shimizu 890ddd
	const TThickQuadratic *curr;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	ctrlPnts.push_back(prev->getThickP0());
Toshihiro Shimizu 890ddd
	ctrlPnts.push_back(prev->getThickP1());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (UINT i = 1; i < curves.size(); ++i) {
Toshihiro Shimizu 890ddd
		curr = curves[i];
Toshihiro Shimizu 890ddd
		assert(curr);
Toshihiro Shimizu 890ddd
		TThickPoint middlePnt = (prev->getThickP2() + curr->getThickP0()) * 0.5;
Toshihiro Shimizu 890ddd
		ctrlPnts.push_back(middlePnt);
Toshihiro Shimizu 890ddd
		ctrlPnts.push_back(curr->getThickP1());
Toshihiro Shimizu 890ddd
		prev = curr;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	ctrlPnts.push_back(prev->getThickP2());
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
inline TThickPoint adapter(const TThickPoint &tp)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return tp;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
inline TThickPoint adapter(const TPointD &p)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return TThickPoint(p);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename t=""></typename>
Toshihiro Shimizu 890ddd
void buildChunksFromControlPoints(QuadStrokeChunkArray &tq,
Toshihiro Shimizu 890ddd
								  const vector<t> &v)</t>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TThickQuadratic *chunk;
Toshihiro Shimizu 890ddd
	T temp;
Toshihiro Shimizu 890ddd
	switch (v.size()) {
Toshihiro Shimizu 890ddd
	case 0:
Toshihiro Shimizu 890ddd
		tq.push_back(new TThickQuadratic);
Toshihiro Shimizu 890ddd
		break;
Toshihiro Shimizu 890ddd
	case 1:
Toshihiro Shimizu 890ddd
		temp = adapter(v.front());
Toshihiro Shimizu 890ddd
		chunk = new TThickQuadratic(temp, temp, temp);
Toshihiro Shimizu 890ddd
		tq.push_back(chunk);
Toshihiro Shimizu 890ddd
		break;
Toshihiro Shimizu 890ddd
	case 2: {
Toshihiro Shimizu 890ddd
		TThickSegment s(adapter(v.front()), adapter(v.back()));
Toshihiro Shimizu 890ddd
		chunk = new TThickQuadratic(s.getThickP0(), s.getThickPoint(0.5), s.getThickP1());
Toshihiro Shimizu 890ddd
		tq.push_back(chunk);
Toshihiro Shimizu 890ddd
	} break;
Toshihiro Shimizu 890ddd
	default:
Toshihiro Shimizu 890ddd
		assert(v.size() & 1); //  v.size() == 2 * chunk + 1
Toshihiro Shimizu 890ddd
		for (UINT i = 0; i < v.size() - 1; i += 2) {
Toshihiro Shimizu 890ddd
			chunk = new TThickQuadratic(adapter(v[i]), adapter(v[i + 1]), adapter(v[i + 2]));
Toshihiro Shimizu 890ddd
			tq.push_back(chunk);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		break;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// WARNING  duplicata in tellipticbrush
Toshihiro Shimizu 890ddd
//  dovrebbe essere eliminata da tellipticbrush perche' qui
Toshihiro Shimizu 890ddd
//  viene usata per  eliminare le strokes a thickness negativa
Toshihiro Shimizu 890ddd
//  evitandone la gestione in tellip...
Toshihiro Shimizu 890ddd
inline bool pairValuesAreEqual(const DoublePair &p)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return p.first == p.second;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// WARNING  duplicata in tellipticbrush
Toshihiro Shimizu 890ddd
//  dovrebbe essere eliminata da tellipticbrush perche' qui
Toshihiro Shimizu 890ddd
//  viene usata per  eliminare le strokes a thickness negativa
Toshihiro Shimizu 890ddd
//  evitandone la gestione in tellip...
Toshihiro Shimizu 890ddd
void analyzeSolution(const vector<double> &coeff, vector<doublepair> &interval)</doublepair></double>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	//  risolve la disequazione  coeff[2]*t^2 + coeff[1]*t + coeff[0] >= 0  in [0, 1] ritornando le soluzioni
Toshihiro Shimizu 890ddd
	//  come sotto-intervalli chiusi di [0, 1] (gli intervalli degeneri [s, s] isolati vengono eliminati)
Toshihiro Shimizu 890ddd
	vector<double> sol;</double>
Toshihiro Shimizu 890ddd
	//int numberOfIntervalSolution = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	rootFinding(coeff, sol);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (isAlmostZero(coeff[2])) {
Toshihiro Shimizu 890ddd
		//  disequazione di 1^ grado
Toshihiro Shimizu 890ddd
		if (isAlmostZero(coeff[1])) {
Toshihiro Shimizu 890ddd
			if (coeff[0] >= 0)
Toshihiro Shimizu 890ddd
				interval.push_back(DoublePair(0.0, 1.0));
Toshihiro Shimizu 890ddd
			return;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		double singleSol = -coeff[0] / coeff[1];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (coeff[1] > 0) {
Toshihiro Shimizu 890ddd
			if (singleSol < 1)
Shinya Kitaoka 12c444
				interval.push_back(DoublePair(std::max(0.0, singleSol), 1.0));
Toshihiro Shimizu 890ddd
		} else {
Toshihiro Shimizu 890ddd
			if (singleSol > 0)
Shinya Kitaoka 12c444
				interval.push_back(DoublePair(0.0, std::min(1.0, singleSol)));
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//  disequazione di 2^ grado effettivo
Toshihiro Shimizu 890ddd
	//double delta = sq(coeff[1]) - 4*coeff[2]*coeff[0];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	sort(sol.begin(), sol.end());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (coeff[2] > 0) {
Toshihiro Shimizu 890ddd
		switch (sol.size()) {
Toshihiro Shimizu 890ddd
		case 0:
Toshihiro Shimizu 890ddd
			interval.push_back(DoublePair(0.0, 1.0));
Toshihiro Shimizu 890ddd
			break;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		case 1:
Toshihiro Shimizu 890ddd
			interval.push_back(DoublePair(0.0, 1.0));
Toshihiro Shimizu 890ddd
			break;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		case 2:
Shinya Kitaoka 12c444
			interval.push_back(DoublePair(0.0, std::min(std::max(sol[0], 0.0), 1.0)));
Shinya Kitaoka 12c444
			interval.push_back(DoublePair(std::max(std::min(sol[1], 1.0), 0.0), 1.0));
Toshihiro Shimizu 890ddd
			break;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	} else if (coeff[2] < 0 && sol.size() == 2)
Shinya Kitaoka 12c444
		interval.push_back(DoublePair(std::min(std::max(sol[0], 0.0), 1.0),
Shinya Kitaoka 12c444
									  std::max(std::min(sol[1], 1.0), 0.0)));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// eat not valid interval
Toshihiro Shimizu 890ddd
	std::vector<doublepair>::iterator it = std::remove_if(interval.begin(),</doublepair>
Toshihiro Shimizu 890ddd
														  interval.end(),
Toshihiro Shimizu 890ddd
														  pairValuesAreEqual);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	interval.erase(it, interval.end());
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void floorNegativeThickness(TThickQuadratic *quad)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	assert(quad);
Toshihiro Shimizu 890ddd
	double val = quad->getThickP0().thick;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (val < 0 && isAlmostZero(val))
Toshihiro Shimizu 890ddd
		quad->setThickP0(TThickPoint(quad->getP0(), 0.0));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	val = quad->getThickP1().thick;
Toshihiro Shimizu 890ddd
	if (val < 0 && isAlmostZero(val))
Toshihiro Shimizu 890ddd
		quad->setThickP1(TThickPoint(quad->getP1(), 0.0));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	val = quad->getThickP2().thick;
Toshihiro Shimizu 890ddd
	if (val < 0 && isAlmostZero(val))
Toshihiro Shimizu 890ddd
		quad->setThickP2(TThickPoint(quad->getP2(), 0.0));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// potrebbe essere realizzata come unary function da usare in una transform
Toshihiro Shimizu 890ddd
void roundNegativeThickess(QuadStrokeChunkArray &v)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	QuadStrokeChunkArray
Toshihiro Shimizu 890ddd
		protoStroke,
Toshihiro Shimizu 890ddd
		tempVectTQ;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TThickQuadratic
Toshihiro Shimizu 890ddd
		*tempTQ = 0,
Toshihiro Shimizu 890ddd
		*tempTQ_1 = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int chunkCount = v.size();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	vector<double> coeff;</double>
Toshihiro Shimizu 890ddd
	double alpha,
Toshihiro Shimizu 890ddd
		beta,
Toshihiro Shimizu 890ddd
		gamma;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	vector<doublepair></doublepair>
Toshihiro Shimizu 890ddd
		positiveIntervals;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (int i = 0; i < chunkCount; ++i) {
Toshihiro Shimizu 890ddd
		const TThickQuadratic &ttq = *v[i];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		alpha = ttq.getThickP0().thick - 2 * ttq.getThickP1().thick + ttq.getThickP2().thick;
Toshihiro Shimizu 890ddd
		beta = 2.0 * (ttq.getThickP1().thick - ttq.getThickP0().thick);
Toshihiro Shimizu 890ddd
		gamma = ttq.getThickP0().thick;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		coeff.push_back(gamma);
Toshihiro Shimizu 890ddd
		coeff.push_back(beta);
Toshihiro Shimizu 890ddd
		coeff.push_back(alpha);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		//  return sotto-intervalli non degeneri di [0, 1] in cui coeff[2]*t^2 + coeff[1]*t + coeff[0] >= 0
Toshihiro Shimizu 890ddd
		analyzeSolution(coeff, positiveIntervals);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		//  il caso isAlmostZero(r(t)) per t in [0, 1] e' gestito direttamente da computeOutline
Toshihiro Shimizu 890ddd
		switch (positiveIntervals.size()) {
Toshihiro Shimizu 890ddd
		case 0: //  r(t) <= 0 per t in [0, 1]
Toshihiro Shimizu 890ddd
			tempTQ = new TThickQuadratic(ttq);
Toshihiro Shimizu 890ddd
			tempTQ->setThickP0(TThickPoint(tempTQ->getP0(), 0.0));
Toshihiro Shimizu 890ddd
			tempTQ->setThickP1(TThickPoint(tempTQ->getP1(), 0.0));
Toshihiro Shimizu 890ddd
			tempTQ->setThickP2(TThickPoint(tempTQ->getP2(), 0.0));
Toshihiro Shimizu 890ddd
			protoStroke.push_back(tempTQ);
Toshihiro Shimizu 890ddd
			break;
Toshihiro Shimizu 890ddd
		case 1:
Toshihiro Shimizu 890ddd
			if (positiveIntervals[0].first == 0.0 &&
Toshihiro Shimizu 890ddd
				positiveIntervals[0].second == 1.0)
Toshihiro Shimizu 890ddd
				protoStroke.push_back(new TThickQuadratic(ttq));
Toshihiro Shimizu 890ddd
			else if (positiveIntervals[0].first == 0.0) {
Toshihiro Shimizu 890ddd
				tempTQ = new TThickQuadratic;
Toshihiro Shimizu 890ddd
				tempTQ_1 = new TThickQuadratic;
Toshihiro Shimizu 890ddd
				ttq.split(positiveIntervals[0].first,
Toshihiro Shimizu 890ddd
						  *tempTQ,
Toshihiro Shimizu 890ddd
						  *tempTQ_1);
Toshihiro Shimizu 890ddd
				tempTQ_1->setThickP0(TThickPoint(tempTQ_1->getP0(), 0.0));
Toshihiro Shimizu 890ddd
				tempTQ_1->setThickP1(TThickPoint(tempTQ_1->getP1(), 0.0));
Toshihiro Shimizu 890ddd
				tempTQ_1->setThickP2(TThickPoint(tempTQ_1->getP2(), 0.0));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				floorNegativeThickness(tempTQ);
Toshihiro Shimizu 890ddd
				protoStroke.push_back(tempTQ);
Toshihiro Shimizu 890ddd
				protoStroke.push_back(tempTQ_1);
Toshihiro Shimizu 890ddd
			} else if (positiveIntervals[0].second == 1.0) {
Toshihiro Shimizu 890ddd
				tempTQ = new TThickQuadratic;
Toshihiro Shimizu 890ddd
				tempTQ_1 = new TThickQuadratic;
Toshihiro Shimizu 890ddd
				ttq.split(positiveIntervals[0].first,
Toshihiro Shimizu 890ddd
						  *tempTQ,
Toshihiro Shimizu 890ddd
						  *tempTQ_1);
Toshihiro Shimizu 890ddd
				tempTQ->setThickP0(TThickPoint(tempTQ->getP0(), 0.0));
Toshihiro Shimizu 890ddd
				tempTQ->setThickP1(TThickPoint(tempTQ->getP1(), 0.0));
Toshihiro Shimizu 890ddd
				tempTQ->setThickP2(TThickPoint(tempTQ->getP2(), 0.0));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				protoStroke.push_back(tempTQ);
Toshihiro Shimizu 890ddd
				floorNegativeThickness(tempTQ_1);
Toshihiro Shimizu 890ddd
				protoStroke.push_back(tempTQ_1);
Toshihiro Shimizu 890ddd
			} else {
Toshihiro Shimizu 890ddd
				coeff.clear();
Toshihiro Shimizu 890ddd
				coeff.push_back(positiveIntervals[0].first);
Toshihiro Shimizu 890ddd
				coeff.push_back(positiveIntervals[0].second);
Toshihiro Shimizu 890ddd
				split<tthickquadratic>(ttq, coeff, tempVectTQ);</tthickquadratic>
Toshihiro Shimizu 890ddd
				assert(tempVectTQ.size() == 3);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				tempVectTQ[0]->setThickP0(TThickPoint(tempVectTQ[0]->getP0(), 0.0));
Toshihiro Shimizu 890ddd
				tempVectTQ[0]->setThickP1(TThickPoint(tempVectTQ[0]->getP1(), 0.0));
Toshihiro Shimizu 890ddd
				tempVectTQ[0]->setThickP2(TThickPoint(tempVectTQ[0]->getP2(), 0.0));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				// controllo che i valori prossimi a zero siano in ogni caso positivi
Toshihiro Shimizu 890ddd
				floorNegativeThickness(tempVectTQ[1]);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				tempVectTQ[2]->setThickP0(TThickPoint(tempVectTQ[2]->getP0(), 0.0));
Toshihiro Shimizu 890ddd
				tempVectTQ[2]->setThickP1(TThickPoint(tempVectTQ[2]->getP1(), 0.0));
Toshihiro Shimizu 890ddd
				tempVectTQ[2]->setThickP2(TThickPoint(tempVectTQ[2]->getP2(), 0.0));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				copy(tempVectTQ.begin(), tempVectTQ.end(), back_inserter(protoStroke));
Toshihiro Shimizu 890ddd
				tempVectTQ.clear(); // non serve una clearPointerArray perchè il possesso
Toshihiro Shimizu 890ddd
									// va alla protoStroke
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
			break;
Toshihiro Shimizu 890ddd
		case 2:
Toshihiro Shimizu 890ddd
			assert(positiveIntervals[0].first == 0.0);
Toshihiro Shimizu 890ddd
			assert(positiveIntervals[1].second == 1.0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			coeff.clear();
Toshihiro Shimizu 890ddd
			coeff.push_back(positiveIntervals[0].second);
Toshihiro Shimizu 890ddd
			coeff.push_back(positiveIntervals[1].first);
Toshihiro Shimizu 890ddd
			split<tthickquadratic>(ttq, coeff, tempVectTQ);</tthickquadratic>
Toshihiro Shimizu 890ddd
			assert(tempVectTQ.size() == 3);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			floorNegativeThickness(tempVectTQ[0]);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			tempVectTQ[1]->setThickP0(TThickPoint(tempVectTQ[1]->getP0(), 0.0));
Toshihiro Shimizu 890ddd
			tempVectTQ[1]->setThickP1(TThickPoint(tempVectTQ[1]->getP1(), 0.0));
Toshihiro Shimizu 890ddd
			tempVectTQ[1]->setThickP2(TThickPoint(tempVectTQ[1]->getP2(), 0.0));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			floorNegativeThickness(tempVectTQ[2]);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			copy(tempVectTQ.begin(), tempVectTQ.end(), back_inserter(protoStroke));
Toshihiro Shimizu 890ddd
			tempVectTQ.clear(); // non serve una clearPointerArray perchè il possesso
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			break;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		positiveIntervals.clear();
Toshihiro Shimizu 890ddd
		coeff.clear();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	swap(protoStroke, v);
Toshihiro Shimizu 890ddd
	clearPointerContainer(protoStroke);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// Some usefuf constant
Toshihiro Shimizu 890ddd
// used in printContainer to set number of row to print
Toshihiro Shimizu 890ddd
const int MAX_ROW = 10;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
inline void changeTQDirection(TThickQuadratic *tq)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TThickPoint p = tq->getThickP2();
Toshihiro Shimizu 890ddd
	tq->setThickP2(tq->getThickP0());
Toshihiro Shimizu 890ddd
	tq->setThickP0(p);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*
Toshihiro Shimizu 890ddd
  //---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
  
Toshihiro Shimizu 890ddd
  double getTQDistance2(const TThickQuadratic& tq, 
Toshihiro Shimizu 890ddd
    const TPointD& p, 
Toshihiro Shimizu 890ddd
    double maxDistance2, 
Toshihiro Shimizu 890ddd
    double& currT)
Toshihiro Shimizu 890ddd
  {
Toshihiro Shimizu 890ddd
    TRectD rect = tq.getBBox();
Toshihiro Shimizu 890ddd
    if (!rect.contains(p))
Toshihiro Shimizu 890ddd
    {
Toshihiro Shimizu 890ddd
      double dist21 = tdistance2(p, rect.getP00());
Toshihiro Shimizu 890ddd
      double dist22 = tdistance2(p, rect.getP01());
Toshihiro Shimizu 890ddd
      double dist23 = tdistance2(p, rect.getP10());
Toshihiro Shimizu 890ddd
      double dist24 = tdistance2(p, rect.getP11());
Toshihiro Shimizu 890ddd
      
Shinya Kitaoka 12c444
      if (std::min(dist21, dist22, dist23, dist24)>=maxDistance2)
Toshihiro Shimizu 890ddd
        return maxDistance2;
Toshihiro Shimizu 890ddd
    }
Toshihiro Shimizu 890ddd
    currT = tq.getT(p);
Toshihiro Shimizu 890ddd
    double dist2 = tdistance2(tq.getPoint(currT), p); 
Toshihiro Shimizu 890ddd
    return (dist2
Toshihiro Shimizu 890ddd
  }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
  //---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
  
Toshihiro Shimizu 890ddd
  template <class class="" k,="" t=""> </class>
Toshihiro Shimizu 890ddd
    void clearMap(std::map<k,t>& v)</k,t>
Toshihiro Shimizu 890ddd
  {
Toshihiro Shimizu 890ddd
    typedef std::map<k,t>::iterator TypeIt;</k,t>
Toshihiro Shimizu 890ddd
    
Toshihiro Shimizu 890ddd
    TypeIt it = v.begin();
Toshihiro Shimizu 890ddd
    
Toshihiro Shimizu 890ddd
    for( ;it!=v.end(); ++it)
Toshihiro Shimizu 890ddd
      delete it->second;
Toshihiro Shimizu 890ddd
    
Toshihiro Shimizu 890ddd
    v.clear();
Toshihiro Shimizu 890ddd
  }
Toshihiro Shimizu 890ddd
  */
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*
Toshihiro Shimizu 890ddd
  Local binary function to find approx values in a vector.
Toshihiro Shimizu 890ddd
  */
Toshihiro Shimizu 890ddd
bool bfAreAlmostEqual(double x, double y)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	double x_y = (x > y) ? x - y : y - x;
Toshihiro Shimizu 890ddd
	return x_y < TConsts::epsilon;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*
Toshihiro Shimizu 890ddd
  Sends values of a container in standard input.
Toshihiro Shimizu 890ddd
  */
Toshihiro Shimizu 890ddd
template <class t=""></class>
Toshihiro Shimizu 890ddd
void printContainer(const T &c, int maxRow = MAX_ROW)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	/*  DA DECOMMENTARE SE NECESSARIO!!!!! 
Toshihiro Shimizu 890ddd
	    //(commentato per non avere dipendenze da tsystem.lib 7/1/2004)
Toshihiro Shimizu 890ddd
    if (maxRow <=0 ) maxRow = MAX_ROW;
Toshihiro Shimizu 890ddd
    
Toshihiro Shimizu 890ddd
    typename T::const_iterator cit;
Toshihiro Shimizu 890ddd
    cit = c.begin();
kogaki 5bbc3c
    ostrstream  oss1;
Toshihiro Shimizu 890ddd
    oss1<<'['<
Toshihiro Shimizu 890ddd
    TSystem::outputDebug( oss1.str() );
Toshihiro Shimizu 890ddd
    oss1.freeze(false);
Toshihiro Shimizu 890ddd
    
Toshihiro Shimizu 890ddd
    int counter = 0;
Toshihiro Shimizu 890ddd
    for( ; cit != c.end(); ++cit)
Toshihiro Shimizu 890ddd
    {
kogaki 5bbc3c
      ostrstream  oss;
Toshihiro Shimizu 890ddd
      if( ++counter == maxRow-1)
Toshihiro Shimizu 890ddd
      {
Toshihiro Shimizu 890ddd
        oss<<'\n';
Toshihiro Shimizu 890ddd
        counter = 0;
Toshihiro Shimizu 890ddd
      }
Toshihiro Shimizu 890ddd
      oss<<(*cit)<<'\n'<<'\0';
Toshihiro Shimizu 890ddd
      TSystem::outputDebug( oss.str() );
Toshihiro Shimizu 890ddd
      oss.freeze(false);
Toshihiro Shimizu 890ddd
    }
Toshihiro Shimizu 890ddd
		*/
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <class t=""></class>
Toshihiro Shimizu 890ddd
void printContainer(ostream &os, const T &c, int maxRow = MAX_ROW)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (maxRow <= 0)
Toshihiro Shimizu 890ddd
		maxRow = MAX_ROW;
Toshihiro Shimizu 890ddd
	typename T::const_iterator cit;
Toshihiro Shimizu 890ddd
	cit = c.begin();
Toshihiro Shimizu 890ddd
	os << '[' << c.size() << ']' << "=\n";
Toshihiro Shimizu 890ddd
	int counter = 0;
Toshihiro Shimizu 890ddd
	for (; cit != c.end(); ++cit) {
Toshihiro Shimizu 890ddd
		if (++counter == maxRow - 1) {
Toshihiro Shimizu 890ddd
			os << '\n';
Toshihiro Shimizu 890ddd
			counter = 0;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		os << (*cit) << ' ';
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <class t=""></class>
Toshihiro Shimizu 890ddd
void printContainerOfPointer(ostream &os, const T &c, int maxRow = MAX_ROW)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (maxRow <= 0)
Toshihiro Shimizu 890ddd
		maxRow = MAX_ROW;
Toshihiro Shimizu 890ddd
	typename T::const_iterator cit;
Toshihiro Shimizu 890ddd
	cit = c.begin();
Toshihiro Shimizu 890ddd
	os << '[' << c.size() << ']' << " - ";
Toshihiro Shimizu 890ddd
	int counter = 0;
Toshihiro Shimizu 890ddd
	for (; cit != c.end(); ++cit) {
Toshihiro Shimizu 890ddd
		if (++counter == maxRow - 1) {
Toshihiro Shimizu 890ddd
			os << '\n';
Toshihiro Shimizu 890ddd
			counter = 0;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		os << **cit << ' ';
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*
Toshihiro Shimizu 890ddd
  Compute a proportion of type x:a=b:c
Toshihiro Shimizu 890ddd
  */
Toshihiro Shimizu 890ddd
template <class t=""></class>
Toshihiro Shimizu 890ddd
T proportion(T a, T b, T c)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	assert(c != T(0));
Toshihiro Shimizu 890ddd
	return a * b / c;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*
Toshihiro Shimizu 890ddd
  Compute a proportion of type x-off:a-off=b:c
Toshihiro Shimizu 890ddd
  */
Toshihiro Shimizu 890ddd
template <class t=""></class>
Toshihiro Shimizu 890ddd
T proportion(T a, T b, T c, T offset)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	assert(c != T(0));
Toshihiro Shimizu 890ddd
	return (a - offset) * b / c + offset;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*!
Toshihiro Shimizu 890ddd
    backinserter
Toshihiro Shimizu 890ddd
   */
Toshihiro Shimizu 890ddd
template 
Toshihiro Shimizu 890ddd
		  typename container_>
Toshihiro Shimizu 890ddd
class TBackInserterPointer
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	container_ &m_c;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	explicit TBackInserterPointer(container_ &c)
Toshihiro Shimizu 890ddd
		: m_c(c){};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TBackInserterPointer &operator=(const type_ *value)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		m_c.push_back(new type_(*value));
Toshihiro Shimizu 890ddd
		return *this;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TBackInserterPointer &operator=(const type_ &value)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		m_c.push_back(new type_(value));
Toshihiro Shimizu 890ddd
		return *this;
Toshihiro Shimizu 890ddd
	};
Toshihiro Shimizu 890ddd
#ifdef MACOSX
Toshihiro Shimizu 890ddd
	typedef type_ value_type;
Toshihiro Shimizu 890ddd
	typedef type_ &reference;
Toshihiro Shimizu 890ddd
	typedef type_ *pointer;
Toshihiro Shimizu 890ddd
	typedef output_iterator_tag iterator_category;
Toshihiro Shimizu 890ddd
	typedef ptrdiff_t difference_type;
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
	/* SIC */
Toshihiro Shimizu 890ddd
	TBackInserterPointer &operator*() { return *this; }
Toshihiro Shimizu 890ddd
	TBackInserterPointer &operator++() { return *this; }
Toshihiro Shimizu 890ddd
	TBackInserterPointer operator++(int val) { return *this; }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
typedef TBackInserterPointer<tthickquadratic, quadstrokechunkarray=""> TThickQuadraticArrayInsertIterator;</tthickquadratic,>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*!
Toshihiro Shimizu 890ddd
  simple adapter for find zero algorithm
Toshihiro Shimizu 890ddd
  */
Toshihiro Shimizu 890ddd
struct computeOffset_ {
Toshihiro Shimizu 890ddd
	TQuadraticLengthEvaluator m_lengthEval;
Toshihiro Shimizu 890ddd
	double m_offset;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	computeOffset_(const TThickQuadratic *ttq,
Toshihiro Shimizu 890ddd
				   double offset)
Toshihiro Shimizu 890ddd
		: m_lengthEval(*ttq), m_offset(offset)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double operator()(double par)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		return m_lengthEval.getLengthAt(par) - m_offset;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*!
Toshihiro Shimizu 890ddd
  simple adapter for find zero algorithm
Toshihiro Shimizu 890ddd
  */
Toshihiro Shimizu 890ddd
struct computeSpeed_ {
Toshihiro Shimizu 890ddd
	const TThickQuadratic *ref_;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	computeSpeed_(const TThickQuadratic *ref)
Toshihiro Shimizu 890ddd
		: ref_(ref)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double operator()(double par)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		return norm(ref_->getSpeed(par));
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
} // end of unnamed namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
const BYTE TStroke::c_selected_flag = 0x1;
Toshihiro Shimizu 890ddd
const BYTE TStroke::c_changed_region_flag = 0x2;
Toshihiro Shimizu 890ddd
const BYTE TStroke::c_dirty_flag = 0x4;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
//
Toshihiro Shimizu 890ddd
// TStroke::Imp
Toshihiro Shimizu 890ddd
//
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
struct TStroke::Imp {
Toshihiro Shimizu 890ddd
	//Geometry-related infos
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	BYTE m_flag;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//! This flag checks if changes occurs and if it is neccessary to update lenght.
Toshihiro Shimizu 890ddd
	bool m_isValidLength;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//! This flag checks if changes occurs and if it is neccessary to update outline.
Toshihiro Shimizu 890ddd
	bool m_isOutlineValid;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//! Control calculus of cache vector.
Toshihiro Shimizu 890ddd
	bool m_areDisabledComputeOfCaches;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//! Bounding Box of a stroke
Toshihiro Shimizu 890ddd
	TRectD m_bBox;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//! This vector contains length computed for  each control point of stroke.
Toshihiro Shimizu 890ddd
	DoubleArray m_partialLenghtArray;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//! This vector contains parameter computed for each control point of stroke.
Toshihiro Shimizu 890ddd
	DoubleArray m_parameterValueAtControlPoint;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//! This vector contains outline of stroke.
Toshihiro Shimizu 890ddd
	QuadStrokeChunkArray m_centerLineArray;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool m_selfLoop;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int m_negativeThicknessPoints;
Toshihiro Shimizu 890ddd
	double m_averageThickness;
Toshihiro Shimizu 890ddd
	double m_maxThickness;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//-------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Not-geometrical vars (style infos)
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int m_id;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int m_styleId;
Toshihiro Shimizu 890ddd
	TStrokeProp *m_prop;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TStroke::OutlineOptions m_outlineOptions;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//-------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	Imp();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	Imp(const vector<tpointd> &v);</tpointd>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	Imp(const vector<tthickpoint> &v);</tthickpoint>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	~Imp()
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		delete m_prop;
Toshihiro Shimizu 890ddd
		clearPointerContainer(m_centerLineArray);
Toshihiro Shimizu 890ddd
		//delete m_style;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void init();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// void  computeOutlines( double pixelSize );
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	inline double getW(int index) { return ((int)m_parameterValueAtControlPoint.size() > index) ? m_parameterValueAtControlPoint[index] : m_parameterValueAtControlPoint.back(); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TRectD computeCenterlineBBox();
Toshihiro Shimizu 890ddd
	/*! 
Toshihiro Shimizu 890ddd
  It computes the bounding box of the subStroke in the parameter range w0-w1.
Toshihiro Shimizu 890ddd
  */
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void computeMaxThickness();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TRectD computeSubBBox(double w0, double w1) const;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	inline QuadStrokeChunkArray &getTQArray()
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		return m_centerLineArray;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	/*! 
Toshihiro Shimizu 890ddd
    Swaps the geometrical infos only
Toshihiro Shimizu 890ddd
  */
Toshihiro Shimizu 890ddd
	void swapGeometry(TStroke::Imp &other) throw();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//! compute cache vector
Toshihiro Shimizu 890ddd
	void computeCacheVector();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	/*!
Toshihiro Shimizu 890ddd
  Set value in m_parameterValueAtControlPoint
Toshihiro Shimizu 890ddd
  */
Toshihiro Shimizu 890ddd
	void computeParameterInControlPoint();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	/*! 
Toshihiro Shimizu 890ddd
  Update parameter in m_parameterValueAtControlPoint 
Toshihiro Shimizu 890ddd
  after insert of control point in stroke.
Toshihiro Shimizu 890ddd
  */
Toshihiro Shimizu 890ddd
	void updateParameterValue(double w,
Toshihiro Shimizu 890ddd
							  UINT chunk,
Toshihiro Shimizu 890ddd
							  TThickQuadratic *tq1,
Toshihiro Shimizu 890ddd
							  TThickQuadratic *tq2);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	/*!
Toshihiro Shimizu 890ddd
    From parameter w retrieves chunk and its parameter ( t in [0,1] ).
Toshihiro Shimizu 890ddd
    Return 
Toshihiro Shimizu 890ddd
    true  ->  error (parameter w out of range, etc)
Toshihiro Shimizu 890ddd
    false ->  ok
Toshihiro Shimizu 890ddd
  */
Toshihiro Shimizu 890ddd
	bool retrieveChunkAndItsParamameter(double w, int &chunk, double &t);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	/*!
Toshihiro Shimizu 890ddd
  From lenght s retrieves chunk and its parameter ( t in [0,1] ).
Toshihiro Shimizu 890ddd
  Return 
Toshihiro Shimizu 890ddd
  true  ->  error (parameter w out of range, etc)
Toshihiro Shimizu 890ddd
  false ->  ok
Toshihiro Shimizu 890ddd
  */
Toshihiro Shimizu 890ddd
	bool retrieveChunkAndItsParamameterAtLength(double s, int &chunk, double &t);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	/*!
Toshihiro Shimizu 890ddd
  Retrieve chunk which contains the n-th control point of stroke.
Toshihiro Shimizu 890ddd
  If control point is between two chunks return the left point.
Toshihiro Shimizu 890ddd
  */
Toshihiro Shimizu 890ddd
	int retrieveChunkFromControlPointIndex(int n)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		assert(0 <= n && n < getControlPointCount());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (n & 1)
Toshihiro Shimizu 890ddd
			++n;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		n >>= 1;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		return n ? n - 1 : n;
Toshihiro Shimizu 890ddd
	};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	/*!
Toshihiro Shimizu 890ddd
  Retrieve range for a chunk.
Toshihiro Shimizu 890ddd
  */
Toshihiro Shimizu 890ddd
	DoublePair retrieveParametersFromChunk(UINT chunk)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		DoublePair outPar;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		int nFirst, nSecond;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		nFirst = chunk * 2;
Toshihiro Shimizu 890ddd
		nSecond = (chunk + 1) * 2;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		outPar.first = getW(nFirst);
Toshihiro Shimizu 890ddd
		outPar.second = getW(nSecond);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		return outPar;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void print(ostream &os);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	inline int getChunkCount() const
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		return m_centerLineArray.size();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	inline int getControlPointCount() const
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		UINT
Toshihiro Shimizu 890ddd
			out = 2 * getChunkCount() + 1;
Toshihiro Shimizu 890ddd
		return out;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TThickQuadratic *getChunk(int index)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		if (0 <= index && index < getChunkCount())
Toshihiro Shimizu 890ddd
			return m_centerLineArray[index];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		return 0;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
private:
Toshihiro Shimizu 890ddd
	// Declared but not defined.
Toshihiro Shimizu 890ddd
	Imp(const Imp &other);
Toshihiro Shimizu 890ddd
	Imp &operator=(const Imp &other);
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
namespace
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
int maxStrokeId = 0;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*! init() is required to initialize all variable 
Toshihiro Shimizu 890ddd
Call init after centerline initialization, because
Toshihiro Shimizu 890ddd
it's necessary to compute BBox
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
void TStroke::Imp::init()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_flag = c_dirty_flag;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_styleId = 1; // DefaultStrokeStyle;
Toshihiro Shimizu 890ddd
	m_prop = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_id = ++maxStrokeId;
Toshihiro Shimizu 890ddd
	m_isValidLength = false;
Toshihiro Shimizu 890ddd
	m_isOutlineValid = false;
Toshihiro Shimizu 890ddd
	m_areDisabledComputeOfCaches = false;
Toshihiro Shimizu 890ddd
	m_selfLoop = false;
Toshihiro Shimizu 890ddd
	m_averageThickness = 0;
Toshihiro Shimizu 890ddd
	m_maxThickness = -1;
Toshihiro Shimizu 890ddd
	m_negativeThicknessPoints = 0;
Toshihiro Shimizu 890ddd
	for (UINT j = 0; j < m_centerLineArray.size(); j++) {
Toshihiro Shimizu 890ddd
		if (m_centerLineArray[j]->getThickP0().thick <= 0)
Toshihiro Shimizu 890ddd
			m_negativeThicknessPoints++;
Toshihiro Shimizu 890ddd
		if (m_centerLineArray[j]->getThickP1().thick <= 0)
Toshihiro Shimizu 890ddd
			m_negativeThicknessPoints++;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	if (!m_centerLineArray.empty() && m_centerLineArray.back()->getThickP2().thick <= 0)
Toshihiro Shimizu 890ddd
		m_negativeThicknessPoints++;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	computeParameterInControlPoint();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TStroke::Imp::Imp()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	init();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TStroke::Imp::Imp(const std::vector<tthickpoint> &v)</tthickpoint>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	buildChunksFromControlPoints(m_centerLineArray, v);
Toshihiro Shimizu 890ddd
	roundNegativeThickess(m_centerLineArray);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	init();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TStroke::Imp::Imp(const std::vector<tpointd> &v)</tpointd>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	buildChunksFromControlPoints(m_centerLineArray, v);
Toshihiro Shimizu 890ddd
	roundNegativeThickess(m_centerLineArray);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	init();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TStroke::Imp::swapGeometry(Imp &other) throw()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	std::swap(m_flag, other.m_flag);
Toshihiro Shimizu 890ddd
	std::swap(m_isValidLength, other.m_isValidLength);
Toshihiro Shimizu 890ddd
	std::swap(m_isOutlineValid, other.m_isOutlineValid);
Toshihiro Shimizu 890ddd
	std::swap(m_areDisabledComputeOfCaches, other.m_areDisabledComputeOfCaches);
Toshihiro Shimizu 890ddd
	std::swap(m_bBox, other.m_bBox);
Toshihiro Shimizu 890ddd
	std::swap(m_partialLenghtArray, other.m_partialLenghtArray);
Toshihiro Shimizu 890ddd
	std::swap(m_parameterValueAtControlPoint, other.m_parameterValueAtControlPoint);
Toshihiro Shimizu 890ddd
	std::swap(m_centerLineArray, other.m_centerLineArray);
Toshihiro Shimizu 890ddd
	std::swap(m_selfLoop, other.m_selfLoop);
Toshihiro Shimizu 890ddd
	std::swap(m_negativeThicknessPoints, other.m_negativeThicknessPoints);
Toshihiro Shimizu 890ddd
	std::swap(m_averageThickness, other.m_averageThickness);
Toshihiro Shimizu 890ddd
	std::swap(m_maxThickness, other.m_maxThickness);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TStroke::Imp::computeMaxThickness()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_maxThickness = m_centerLineArray[0]->getThickP0().thick;
Toshihiro Shimizu 890ddd
	for (UINT i = 0; i < m_centerLineArray.size(); i++)
Shinya Kitaoka 12c444
		m_maxThickness = std::max({m_maxThickness, m_centerLineArray[i]->getThickP1().thick, m_centerLineArray[i]->getThickP2().thick});
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TStroke::Imp::computeCacheVector()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	// se la stroke e' stata invalidata a causa dell'inserimento di punti
Toshihiro Shimizu 890ddd
	//  di controllo o dal ricampionamento
Toshihiro Shimizu 890ddd
	if (!m_areDisabledComputeOfCaches && !m_isValidLength) {
Toshihiro Shimizu 890ddd
		if (getChunkCount() > 0) // se ci sono cionchi
Toshihiro Shimizu 890ddd
		{
Toshihiro Shimizu 890ddd
			// (re)inizializzo un vettore
Toshihiro Shimizu 890ddd
			m_partialLenghtArray.resize(getControlPointCount(), (std::numeric_limits<double>::max)());</double>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			m_partialLenghtArray[0] = 0.0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			double length = 0.0;
Toshihiro Shimizu 890ddd
			int j = 0;
Toshihiro Shimizu 890ddd
			const TThickQuadratic *tq;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			TQuadraticLengthEvaluator lengthEvaluator;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			for (int i = 0; i < getChunkCount(); ++i) {
Toshihiro Shimizu 890ddd
				assert(j <= getControlPointCount());
Toshihiro Shimizu 890ddd
				tq = getChunk(i);
Toshihiro Shimizu 890ddd
				lengthEvaluator.setQuad(*tq);
Toshihiro Shimizu 890ddd
				m_partialLenghtArray[j++] = length;
Toshihiro Shimizu 890ddd
				m_partialLenghtArray[j++] = length + lengthEvaluator.getLengthAt(0.5);
Toshihiro Shimizu 890ddd
				length += lengthEvaluator.getLengthAt(1.0);
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			m_partialLenghtArray[j++] = length;
Toshihiro Shimizu 890ddd
			assert(j == getControlPointCount());
Toshihiro Shimizu 890ddd
			// assert( m_parameterValueAtControlPoint.size() == m_partialLenghtArray.size() );
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		m_isValidLength = true;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TStroke::Imp::computeParameterInControlPoint()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (!m_areDisabledComputeOfCaches) {
Toshihiro Shimizu 890ddd
		// questa funzione ricalcola i valori dei parametri nei cionchi
Toshihiro Shimizu 890ddd
		//  N.B. deve essere richiamata quando si effettuano inserimenti
Toshihiro Shimizu 890ddd
		//    di punti di controllo che cambiano la lunghezza della curva
Toshihiro Shimizu 890ddd
		//  insert, push e costruttore
Toshihiro Shimizu 890ddd
		if (!getChunkCount()) {
Toshihiro Shimizu 890ddd
			m_parameterValueAtControlPoint.clear();
Toshihiro Shimizu 890ddd
			return;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		int controlPointCount = getControlPointCount();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		m_parameterValueAtControlPoint.resize(controlPointCount, 0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// N.B. number of control point is reduced of 1
Toshihiro Shimizu 890ddd
		--controlPointCount;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		double
Toshihiro Shimizu 890ddd
			val = 0.0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		assert(controlPointCount >= 0.0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		for (int i = 0; i <= controlPointCount; ++i) {
Toshihiro Shimizu 890ddd
			val = i / (double)controlPointCount;
Toshihiro Shimizu 890ddd
			m_parameterValueAtControlPoint[i] = val;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TStroke::Imp::updateParameterValue(double w,
Toshihiro Shimizu 890ddd
										UINT chunk,
Toshihiro Shimizu 890ddd
										TThickQuadratic *tq1,
Toshihiro Shimizu 890ddd
										TThickQuadratic *tq2)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	DoublePair p = retrieveParametersFromChunk(chunk);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	UINT controlPointToErase = 2 * chunk + 1;
Toshihiro Shimizu 890ddd
	DoubleIt it = m_parameterValueAtControlPoint.begin();
Toshihiro Shimizu 890ddd
	std::advance(it, controlPointToErase);
Toshihiro Shimizu 890ddd
	m_parameterValueAtControlPoint.erase(it);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double normalizedParam = tq2->getT(tq2->getP1());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	std::vector<double>::iterator first;</double>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	normalizedParam = proportion(p.second, normalizedParam, 1.0, w);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	first = std::upper_bound(
Toshihiro Shimizu 890ddd
		m_parameterValueAtControlPoint.begin(),
Toshihiro Shimizu 890ddd
		m_parameterValueAtControlPoint.end(),
Toshihiro Shimizu 890ddd
		normalizedParam);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (first != m_parameterValueAtControlPoint.end()) {
Toshihiro Shimizu 890ddd
		first = m_parameterValueAtControlPoint.insert(first, normalizedParam);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		first = m_parameterValueAtControlPoint.insert(first, w);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		normalizedParam = tq1->getT(tq1->getP1());
Toshihiro Shimizu 890ddd
		normalizedParam = proportion(w, normalizedParam, 1.0, p.first);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		m_parameterValueAtControlPoint.insert(first, normalizedParam);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	/* FAB
Toshihiro Shimizu 890ddd
  assert( getControlPointCount() <= 
Toshihiro Shimizu 890ddd
          (int)m_parameterValueAtControlPoint.size() );
Toshihiro Shimizu 890ddd
   //*/
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool TStroke::getChunkAndTAtLength(double s, int &chunk, double &t) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return m_imp->retrieveChunkAndItsParamameterAtLength(s, chunk, t);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool TStroke::Imp::retrieveChunkAndItsParamameterAtLength(double s, int &chunk, double &t)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	vector<double>::iterator first;</double>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// cerco nella cache la posizione che compete alla lunghezza s
Toshihiro Shimizu 890ddd
	first = std::upper_bound(m_partialLenghtArray.begin(),
Toshihiro Shimizu 890ddd
							 m_partialLenghtArray.end(),
Toshihiro Shimizu 890ddd
							 s);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// se s e' interna al vettore di cache
Toshihiro Shimizu 890ddd
	if (first != m_partialLenghtArray.end()) {
Toshihiro Shimizu 890ddd
		// individuo il punto di controllo della stroke...
Toshihiro Shimizu 890ddd
		int controlPointOffset = distance(m_partialLenghtArray.begin(), first);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// ...e da questo il cionco relativo.
Toshihiro Shimizu 890ddd
		chunk = retrieveChunkFromControlPointIndex(controlPointOffset);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (first != m_partialLenghtArray.begin() && s == *(first - 1)) {
Toshihiro Shimizu 890ddd
			controlPointOffset--;
Toshihiro Shimizu 890ddd
			if (controlPointOffset & 1) {
Toshihiro Shimizu 890ddd
				const DoublePair &p = retrieveParametersFromChunk(chunk);
Toshihiro Shimizu 890ddd
				t = proportion(1.0, getW(controlPointOffset) - p.first, p.second - p.first);
Toshihiro Shimizu 890ddd
			} else
Toshihiro Shimizu 890ddd
				t = 0.0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			return false;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// fisso un offset per l'algoritmo di bisezione
Toshihiro Shimizu 890ddd
		double
Toshihiro Shimizu 890ddd
			offset = (first == m_partialLenghtArray.begin()) ? s : s - m_partialLenghtArray[chunk * 2];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// cerco il parametro minimo a meno di una tolleranza epsilon
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		const double tol = TConsts::epsilon * 0.1;
Toshihiro Shimizu 890ddd
		int err;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		computeOffset_ op(getChunk(chunk), offset);
Toshihiro Shimizu 890ddd
		computeSpeed_ op2(getChunk(chunk));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (!findZero_Newton(0.0,
Toshihiro Shimizu 890ddd
							 1.0,
Toshihiro Shimizu 890ddd
							 op,
Toshihiro Shimizu 890ddd
							 op2,
Toshihiro Shimizu 890ddd
							 tol,
Toshihiro Shimizu 890ddd
							 tol,
Toshihiro Shimizu 890ddd
							 100,
Toshihiro Shimizu 890ddd
							 t,
Toshihiro Shimizu 890ddd
							 err))
Toshihiro Shimizu 890ddd
			t = -1; // if can not find a good value set parameter to error value
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// se l'algoritmo di ricerca ha fallito fissa il valore ad uno dei due estremi
Toshihiro Shimizu 890ddd
		if (t == -1) {
Toshihiro Shimizu 890ddd
			if (s <= m_partialLenghtArray[controlPointOffset])
Toshihiro Shimizu 890ddd
				t = 0.0;
Toshihiro Shimizu 890ddd
			t = 1.0;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (s <= 0.0) {
Toshihiro Shimizu 890ddd
		chunk = 0;
Toshihiro Shimizu 890ddd
		t = 0.0;
Toshihiro Shimizu 890ddd
	} else if (s >= m_partialLenghtArray.back()) {
Toshihiro Shimizu 890ddd
		chunk = getChunkCount() - 1;
Toshihiro Shimizu 890ddd
		t = 1.0;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return false;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool TStroke::getChunkAndT(double w, int &chunk, double &t) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return m_imp->retrieveChunkAndItsParamameter(w, chunk, t);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool TStroke::Imp::retrieveChunkAndItsParamameter(double w, int &chunk, double &t)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	vector<double>::iterator first;</double>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// trova l'iteratore alla prima posizione che risulta maggiore o uguale a w
Toshihiro Shimizu 890ddd
	first = std::lower_bound(m_parameterValueAtControlPoint.begin(),
Toshihiro Shimizu 890ddd
							 m_parameterValueAtControlPoint.end(),
Toshihiro Shimizu 890ddd
							 w);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// se non e' stato possibile trovare w nel vettore ritorna errore
Toshihiro Shimizu 890ddd
	if (first == m_parameterValueAtControlPoint.end())
Toshihiro Shimizu 890ddd
		return true;
Toshihiro Shimizu 890ddd
	/* FAB
Toshihiro Shimizu 890ddd
  double
Toshihiro Shimizu 890ddd
    found = *first;
Toshihiro Shimizu 890ddd
  assert(found  <=  *first);
Toshihiro Shimizu 890ddd
  //*/
Toshihiro Shimizu 890ddd
	// individuo il punto di controllo che compete alla posizione nel vettore
Toshihiro Shimizu 890ddd
	int controlPointOffset = distance(m_parameterValueAtControlPoint.begin(), first);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// individuo il cionco relativo al punto di controllo
Toshihiro Shimizu 890ddd
	chunk = retrieveChunkFromControlPointIndex(controlPointOffset);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// calcolo il parametro relativo al cionco
Toshihiro Shimizu 890ddd
	DoublePair
Toshihiro Shimizu 890ddd
		p = retrieveParametersFromChunk(chunk);
Toshihiro Shimizu 890ddd
	/* FAB
Toshihiro Shimizu 890ddd
  assert( p.first <= w &&
Toshihiro Shimizu 890ddd
          w <= p.second );
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef  _DEBUG
Toshihiro Shimizu 890ddd
  chunk = retrieveChunkFromControlPointIndex( controlPointOffset );
Toshihiro Shimizu 890ddd
  p = retrieveParametersFromChunk( chunk );  
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
  //*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (w < p.first ||
Toshihiro Shimizu 890ddd
		w > p.second) {
Toshihiro Shimizu 890ddd
		t = (p.first + p.second) * 0.5;
Toshihiro Shimizu 890ddd
	} else
Toshihiro Shimizu 890ddd
		t = proportion(1.0, w - p.first, p.second - p.first);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	/* FAB
Toshihiro Shimizu 890ddd
  assert( 0.0 <= t && t <= 1.0 ); 
Toshihiro Shimizu 890ddd
  //*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return false;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TRectD TStroke::Imp::computeCenterlineBBox()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	UINT n = m_centerLineArray.size();
Toshihiro Shimizu 890ddd
	if (m_centerLineArray.empty())
Toshihiro Shimizu 890ddd
		return TRectD();
Toshihiro Shimizu 890ddd
	TQuadratic q(m_centerLineArray[0]->getP0(), m_centerLineArray[0]->getP1(), m_centerLineArray[0]->getP2());
Toshihiro Shimizu 890ddd
	TRectD bbox = q.getBBox();
Toshihiro Shimizu 890ddd
	for (UINT i = 1; i < n; i++) {
Toshihiro Shimizu 890ddd
		q = TQuadratic(m_centerLineArray[i]->getP0(), m_centerLineArray[i]->getP1(), m_centerLineArray[i]->getP2());
Toshihiro Shimizu 890ddd
		bbox += q.getBBox();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	return bbox;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TRectD TStroke::Imp::computeSubBBox(double w0, double w1) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (m_centerLineArray.empty())
Toshihiro Shimizu 890ddd
		return TRectD();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int n = m_centerLineArray.size();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TRectD bBox;
Toshihiro Shimizu 890ddd
	const double eps = 0.000000001;
Toshihiro Shimizu 890ddd
	int i;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (w0 > w1)
Toshihiro Shimizu 890ddd
		tswap(w0, w1);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double nw0 = w0 * n;
Toshihiro Shimizu 890ddd
	double nw1 = w1 * n;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int i0 = (int)nw0; //indice della quadrica che contiene w0
Toshihiro Shimizu 890ddd
	int i1 = (int)nw1; //idem per w1
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double t0 = nw0 - (double)i0; //parametro di w0 rispetto alla quadrica che lo contiene
Toshihiro Shimizu 890ddd
	double t1 = nw1 - (double)i1; //idem per w1
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (t0 < eps) // se t0 e' quasi uguale a zero, evito di fare lo split e considero tutta la quadrica i0
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		i0--;
Toshihiro Shimizu 890ddd
		t0 = 1.0;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	if (t1 > (1 - eps)) //se t1 e' quasi uguale a uno, evito di fare lo split e considero tutta la quadrica i1
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		i1++;
Toshihiro Shimizu 890ddd
		t1 = 0.0;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TThickQuadratic quadratic1, quadratic2, quadratic3;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (i0 == i1) // i due punti di taglio capitano nella stessa quadratica
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		if (t0 < eps && t1 > (1 - eps))
Toshihiro Shimizu 890ddd
			return m_centerLineArray[i0]->getBBox();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (t0 < eps) {
Toshihiro Shimizu 890ddd
			m_centerLineArray[i0]->split(t1, quadratic1, quadratic2);
Toshihiro Shimizu 890ddd
			return quadratic1.getBBox();
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (t1 > (1 - eps)) {
Toshihiro Shimizu 890ddd
			m_centerLineArray[i0]->split(t0, quadratic1, quadratic2);
Toshihiro Shimizu 890ddd
			return quadratic2.getBBox();
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// quadratic1 e' la quadratica risultante dallo split tra t0 e t1 di m_centerLineArray[i0]
Toshihiro Shimizu 890ddd
		m_centerLineArray[i0]->split(t0, quadratic1, quadratic2);
Toshihiro Shimizu 890ddd
		quadratic2.split((t1 - t0) / (1 - t0), quadratic1, quadratic3);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		return quadratic1.getBBox();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// se i due punti di taglio capitano in quadratiche diverse
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//sommo le bbox di quelle interne
Toshihiro Shimizu 890ddd
	for (i = i0 + 1; i < i1; i++)
Toshihiro Shimizu 890ddd
		bBox += m_centerLineArray[i]->getBBox();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// e sommo le bbox delle quadratiche splittate agli estremi se non sono irrilevanti
Toshihiro Shimizu 890ddd
	if (i0 >= 0 && t0 < (1 - eps)) {
Toshihiro Shimizu 890ddd
		m_centerLineArray[i0]->split(t0, quadratic1, quadratic2);
Toshihiro Shimizu 890ddd
		bBox += quadratic2.getBBox();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (i1 < n && t1 > eps) {
Toshihiro Shimizu 890ddd
		m_centerLineArray[i1]->split(t1, quadratic1, quadratic2);
Toshihiro Shimizu 890ddd
		bBox += quadratic1.getBBox();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return bBox;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TStroke::Imp::print(ostream &os)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
#if defined(_DEBUG) || defined(DEBUG)
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	os << "m_isValidLength:" << m_isValidLength << endl;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	os << "m_isOutlineValid:" << m_isOutlineValid << endl;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	os << "m_areDisabledComputeOfCaches:" << m_areDisabledComputeOfCaches << endl;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	os << "m_bBox:" << m_bBox << endl;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	os << "m_partialLenghtArray";
Toshihiro Shimizu 890ddd
	printContainer(os, m_partialLenghtArray);
Toshihiro Shimizu 890ddd
	os << endl;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	os << "m_parameterValueAtControlPoint";
Toshihiro Shimizu 890ddd
	printContainer(os, m_parameterValueAtControlPoint);
Toshihiro Shimizu 890ddd
	os << endl;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	os << "m_centerLineArray";
Toshihiro Shimizu 890ddd
	//os.setf(myIOFlags::scientific);
Toshihiro Shimizu 890ddd
	printContainerOfPointer(os, m_centerLineArray);
Toshihiro Shimizu 890ddd
	os << endl;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*
Toshihiro Shimizu 890ddd
  vector<tpixel> m_outlineColorArray;</tpixel>
Toshihiro Shimizu 890ddd
  
Toshihiro Shimizu 890ddd
    vector<tpointd> m_texArray;</tpointd>
Toshihiro Shimizu 890ddd
    
Toshihiro Shimizu 890ddd
      TFilePath m_filePath;
Toshihiro Shimizu 890ddd
      TRasterP  m_texture;
Toshihiro Shimizu 890ddd
  */
Toshihiro Shimizu 890ddd
// TSystem::outputDebug( os.str());
Toshihiro Shimizu 890ddd
#else
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//  Needed to DEBUG
Toshihiro Shimizu 890ddd
DEFINE_CLASS_CODE(TStroke, 15)
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// Costructor
Toshihiro Shimizu 890ddd
TStroke::TStroke()
Toshihiro Shimizu 890ddd
	: TSmartObject(m_classCode)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	vector<tthickpoint> p(3);</tthickpoint>
Toshihiro Shimizu 890ddd
	p[0] = TThickPoint(0, 0, 0);
Toshihiro Shimizu 890ddd
	p[1] = p[0];
Toshihiro Shimizu 890ddd
	p[2] = p[1];
Toshihiro Shimizu 890ddd
Shinya Kitaoka 262a92
	m_imp.reset(new TStroke::Imp(p));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	/*
Toshihiro Shimizu 890ddd
  // da fissare deve trovarsi prima della init
Toshihiro Shimizu 890ddd
  m_imp->m_centerLineArray.push_back ( new TThickQuadratic );
Toshihiro Shimizu 890ddd
  */
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// Build a stroke from a set of ThickPoint
Toshihiro Shimizu 890ddd
TStroke::TStroke(const vector<tthickpoint> &v)</tthickpoint>
Toshihiro Shimizu 890ddd
	: TSmartObject(m_classCode)
Shinya Kitaoka 262a92
	, m_imp(new TStroke::Imp(v))
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TStroke::TStroke(const vector<tpointd> &v)</tpointd>
Toshihiro Shimizu 890ddd
	: TSmartObject(m_classCode)
Shinya Kitaoka 262a92
	, m_imp(new TStroke::Imp(v))
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TStroke::~TStroke()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TStroke::TStroke(const TStroke &other)
Toshihiro Shimizu 890ddd
	: TSmartObject(m_classCode)
Shinya Kitaoka 262a92
	, m_imp(new TStroke::Imp())
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_imp->m_bBox = other.getBBox();
Toshihiro Shimizu 890ddd
	m_imp->m_isValidLength = other.m_imp->m_isValidLength;
Toshihiro Shimizu 890ddd
	m_imp->m_isOutlineValid = other.m_imp->m_isOutlineValid;
Toshihiro Shimizu 890ddd
	m_imp->m_areDisabledComputeOfCaches = other.m_imp->m_areDisabledComputeOfCaches;
Toshihiro Shimizu 890ddd
	m_imp->m_flag = other.m_imp->m_flag;
Toshihiro Shimizu 890ddd
	m_imp->m_outlineOptions = other.m_imp->m_outlineOptions;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Are they sure as regards exceptions ?
Toshihiro Shimizu 890ddd
	m_imp->m_centerLineArray.resize(other.m_imp->m_centerLineArray.size());
Toshihiro Shimizu 890ddd
	int i;
Toshihiro Shimizu 890ddd
	for (i = 0; i < (int)other.m_imp->m_centerLineArray.size(); i++)
Toshihiro Shimizu 890ddd
		m_imp->m_centerLineArray[i] = new TThickQuadratic(*other.m_imp->m_centerLineArray[i]);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//copy(  other.m_imp->m_centerLineArray.begin(),
Toshihiro Shimizu 890ddd
	//   other.m_imp->m_centerLineArray.end(),
Toshihiro Shimizu 890ddd
	//   TThickQuadraticArrayInsertIterator(m_imp->m_centerLineArray));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	copy(other.m_imp->m_partialLenghtArray.begin(),
Toshihiro Shimizu 890ddd
		 other.m_imp->m_partialLenghtArray.end(),
Toshihiro Shimizu 890ddd
		 back_inserter<doublearray>(m_imp->m_partialLenghtArray));</doublearray>
Toshihiro Shimizu 890ddd
	copy(other.m_imp->m_parameterValueAtControlPoint.begin(),
Toshihiro Shimizu 890ddd
		 other.m_imp->m_parameterValueAtControlPoint.end(),
Toshihiro Shimizu 890ddd
		 back_inserter<doublearray>(m_imp->m_parameterValueAtControlPoint));</doublearray>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_imp->m_styleId = other.m_imp->m_styleId;
Toshihiro Shimizu 890ddd
	m_imp->m_prop = 0; //other.m_imp->m_prop ? other.m_imp->m_prop->clone(this) : 0;
Toshihiro Shimizu 890ddd
	m_imp->m_selfLoop = other.m_imp->m_selfLoop;
Toshihiro Shimizu 890ddd
	m_imp->m_negativeThicknessPoints = other.m_imp->m_negativeThicknessPoints;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TStroke &TStroke::operator=(const TStroke &other)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TStroke temp(other);
Toshihiro Shimizu 890ddd
	swap(temp);
Toshihiro Shimizu 890ddd
	return *this;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool TStroke::getNearestW(const TPointD &p,
Toshihiro Shimizu 890ddd
						  double &outW,
Toshihiro Shimizu 890ddd
						  double &dist2,
Toshihiro Shimizu 890ddd
						  bool checkBBox) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	double outT;
Toshihiro Shimizu 890ddd
	int chunkIndex;
Toshihiro Shimizu 890ddd
	bool ret = getNearestChunk(p, outT, chunkIndex, dist2, checkBBox);
Toshihiro Shimizu 890ddd
	if (ret)
Toshihiro Shimizu 890ddd
		outW = getW(chunkIndex, outT);
Toshihiro Shimizu 890ddd
	return ret;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool TStroke::getNearestChunk(const TPointD &p,
Toshihiro Shimizu 890ddd
							  double &outT,
Toshihiro Shimizu 890ddd
							  int &chunkIndex,
Toshihiro Shimizu 890ddd
							  double &dist2,
Toshihiro Shimizu 890ddd
							  bool checkBBox) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	dist2 = (numeric_limits<double>::max)();</double>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (UINT i = 0; i < m_imp->m_centerLineArray.size(); i++) {
Toshihiro Shimizu 890ddd
		if (checkBBox && !m_imp->m_centerLineArray[i]->getBBox().enlarge(30).contains(p))
Toshihiro Shimizu 890ddd
			continue;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		double t = (m_imp->m_centerLineArray)[i]->getT(p);
Toshihiro Shimizu 890ddd
		double dist = tdistance2((m_imp->m_centerLineArray)[i]->getPoint(t), p);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (dist < dist2) {
Toshihiro Shimizu 890ddd
			dist2 = dist;
Toshihiro Shimizu 890ddd
			chunkIndex = i;
Toshihiro Shimizu 890ddd
			outT = t;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return dist2 < (numeric_limits<double>::max)();</double>
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
//finds all points on stroke which are "enough" close to point p. return the number of such points.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
int TStroke::getNearChunks(const TThickPoint &p,
Toshihiro Shimizu 890ddd
						   vector<tthickpoint> &pointsOnStroke,</tthickpoint>
Toshihiro Shimizu 890ddd
						   bool checkBBox) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int currIndex = -100;
Toshihiro Shimizu 890ddd
	double currDist2 = 100000;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (UINT i = 0; i < m_imp->m_centerLineArray.size(); i++) {
Toshihiro Shimizu 890ddd
		TThickQuadratic *q = m_imp->m_centerLineArray[i];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (checkBBox && !q->getBBox().enlarge(30).contains(p))
Toshihiro Shimizu 890ddd
			continue;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		double t = q->getT(p);
Toshihiro Shimizu 890ddd
		TThickPoint p1 = q->getThickPoint(t);
Toshihiro Shimizu 890ddd
		double dist2 = tdistance2(p1, p);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (dist2 < (p1.thick + p.thick + 5) * (p1.thick + p.thick + 5)) {
Toshihiro Shimizu 890ddd
			if (!pointsOnStroke.empty() && areAlmostEqual(p1, pointsOnStroke.back(), 1e-3))
Toshihiro Shimizu 890ddd
				continue;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			if (currIndex == i - 1) {
Toshihiro Shimizu 890ddd
				if (dist2 < currDist2)
Toshihiro Shimizu 890ddd
					pointsOnStroke.pop_back();
Toshihiro Shimizu 890ddd
				else
Toshihiro Shimizu 890ddd
					continue;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			currIndex = i;
Toshihiro Shimizu 890ddd
			currDist2 = dist2;
Toshihiro Shimizu 890ddd
			pointsOnStroke.push_back(p1);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return pointsOnStroke.size(); //dist2 < (numeric_limits<double>::max)();</double>
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TStroke::getControlPoints(vector<tthickpoint> &v) const</tthickpoint>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	assert(v.empty());
Toshihiro Shimizu 890ddd
	v.resize(m_imp->m_centerLineArray.size() * 2 + 1);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	v[0] = m_imp->m_centerLineArray[0]->getThickP0();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (UINT i = 0; i < m_imp->m_centerLineArray.size(); i++) {
Toshihiro Shimizu 890ddd
		TThickQuadratic *q = m_imp->m_centerLineArray[i];
Toshihiro Shimizu 890ddd
		v[2 * i + 1] = q->getThickP1();
Toshihiro Shimizu 890ddd
		v[2 * i + 2] = q->getThickP2();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TThickPoint TStroke::getControlPoint(int n) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (n <= 0)
Toshihiro Shimizu 890ddd
		return m_imp->m_centerLineArray.front()->getThickP0();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (n >= getControlPointCount())
Toshihiro Shimizu 890ddd
		return m_imp->m_centerLineArray.back()->getThickP2();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// calcolo l'offset del chunk risolvendo l'equazione
Toshihiro Shimizu 890ddd
	//  2 * chunkNumber + 1 = n
Toshihiro Shimizu 890ddd
	//  chunkNumber = tceil((n - 1) / 2)
Toshihiro Shimizu 890ddd
	int chunkNumber = tceil((n - 1) * 0.5);
Toshihiro Shimizu 890ddd
	assert(chunkNumber <= getChunkCount());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int pointOffset = n - chunkNumber * 2;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (chunkNumber == getChunkCount()) // e' l'ultimo punto della stroke
Toshihiro Shimizu 890ddd
		return getChunk(chunkNumber - 1)->getThickP2();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	switch (pointOffset) {
Toshihiro Shimizu 890ddd
	case 0:
Toshihiro Shimizu 890ddd
		return getChunk(chunkNumber)->getThickP0();
Toshihiro Shimizu 890ddd
	case 1:
Toshihiro Shimizu 890ddd
		return getChunk(chunkNumber)->getThickP1();
Toshihiro Shimizu 890ddd
	case 2:
Toshihiro Shimizu 890ddd
		return getChunk(chunkNumber)->getThickP2();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	assert("Not yet finished" && false);
Toshihiro Shimizu 890ddd
	return getControlPoint(0);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TThickPoint TStroke::getControlPointAtParameter(double w) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (w <= 0)
Toshihiro Shimizu 890ddd
		return m_imp->m_centerLineArray.front()->getThickP0();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (w >= 1.0)
Toshihiro Shimizu 890ddd
		return m_imp->m_centerLineArray.back()->getThickP2();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	vector<double>::iterator</double>
Toshihiro Shimizu 890ddd
		it_begin = m_imp->m_parameterValueAtControlPoint.begin(),
Toshihiro Shimizu 890ddd
		first,
Toshihiro Shimizu 890ddd
		it_end = m_imp->m_parameterValueAtControlPoint.end();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// find iterator at position greater or equal to w
Toshihiro Shimizu 890ddd
	first = std::lower_bound(it_begin, it_end, w);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	assert(first != it_end);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// now is possible to get control point
Toshihiro Shimizu 890ddd
	//if( areAlmostEqual(*first, w, 0.1) )
Toshihiro Shimizu 890ddd
	//  return  getControlPoint( distance(it_begin, first) );
Toshihiro Shimizu 890ddd
	if (first == it_begin)
Toshihiro Shimizu 890ddd
		return getControlPoint(0);
Toshihiro Shimizu 890ddd
	else if ((*first - w) <= w - *(first - 1))
Toshihiro Shimizu 890ddd
		return getControlPoint(distance(it_begin, first));
Toshihiro Shimizu 890ddd
	else
Toshihiro Shimizu 890ddd
		return getControlPoint(distance(it_begin, first - 1));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
int TStroke::getControlPointIndexAfterParameter(double w) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	const vector<double>::const_iterator</double>
Toshihiro Shimizu 890ddd
		begin = m_imp->m_parameterValueAtControlPoint.begin(),
Toshihiro Shimizu 890ddd
		end = m_imp->m_parameterValueAtControlPoint.end();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	vector<double>::const_iterator it =</double>
Toshihiro Shimizu 890ddd
		std::upper_bound(begin, end, w);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (it == end)
Toshihiro Shimizu 890ddd
		return getControlPointCount();
Toshihiro Shimizu 890ddd
	else
Toshihiro Shimizu 890ddd
		return std::distance(begin, it);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TStroke::setControlPoint(int n, const TThickPoint &pos)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	assert(n >= 0);
Toshihiro Shimizu 890ddd
	assert(n < getControlPointCount());
Toshihiro Shimizu 890ddd
	if (n < 0 || n >= getControlPointCount())
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	invalidate();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	QuadStrokeChunkArray &chunkArray = m_imp->m_centerLineArray;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (getControlPoint(n).thick <= 0 && pos.thick > 0)
Toshihiro Shimizu 890ddd
		m_imp->m_negativeThicknessPoints--;
Toshihiro Shimizu 890ddd
	else if (getControlPoint(n).thick > 0 && pos.thick <= 0)
Toshihiro Shimizu 890ddd
		m_imp->m_negativeThicknessPoints++;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (n == 0) {
Toshihiro Shimizu 890ddd
		chunkArray[0]->setThickP0(pos);
Toshihiro Shimizu 890ddd
		//m_imp->computeBBox();
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int chunkNumber = tceil((n - 1) * 0.5);
Toshihiro Shimizu 890ddd
	assert(chunkNumber <= getChunkCount());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int pointOffset = n - chunkNumber * 2;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (chunkNumber == getChunkCount()) // e' l'ultimo punto della stroke
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		chunkArray[chunkNumber - 1]->setThickP2(pos);
Toshihiro Shimizu 890ddd
		//m_imp->computeBBox();
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (0 == pointOffset) {
Toshihiro Shimizu 890ddd
		chunkArray[chunkNumber]->setThickP0(pos);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (chunkNumber >= 1) {
Toshihiro Shimizu 890ddd
			chunkNumber--;
Toshihiro Shimizu 890ddd
			chunkArray[chunkNumber]->setThickP2(pos);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	} else if (1 == pointOffset)
Toshihiro Shimizu 890ddd
		chunkArray[chunkNumber]->setThickP1(pos);
Toshihiro Shimizu 890ddd
	else if (2 == pointOffset) {
Toshihiro Shimizu 890ddd
		chunkArray[chunkNumber]->setThickP2(pos);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (chunkNumber < getChunkCount() - 1) {
Toshihiro Shimizu 890ddd
			chunkNumber++;
Toshihiro Shimizu 890ddd
			chunkArray[chunkNumber]->setThickP0(pos);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	//m_imp->computeBBox();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//! Ridisegna lo stroke
Toshihiro Shimizu 890ddd
void TStroke::reshape(const TThickPoint pos[], int count)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	// count deve essere dispari e maggiore o uguale a tre
Toshihiro Shimizu 890ddd
	assert(count >= 3);
Toshihiro Shimizu 890ddd
	assert(count & 1);
Toshihiro Shimizu 890ddd
	QuadStrokeChunkArray &chunkArray = m_imp->m_centerLineArray;
Toshihiro Shimizu 890ddd
	clearPointerContainer(chunkArray);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_imp->m_negativeThicknessPoints = 0;
Toshihiro Shimizu 890ddd
	for (int i = 0; i < count - 1; i += 2) {
Toshihiro Shimizu 890ddd
		chunkArray.push_back(new TThickQuadratic(pos[i], pos[i + 1], pos[i + 2]));
Toshihiro Shimizu 890ddd
		if (pos[i].thick <= 0)
Toshihiro Shimizu 890ddd
			m_imp->m_negativeThicknessPoints++;
Toshihiro Shimizu 890ddd
		if (pos[i + 1].thick <= 0)
Toshihiro Shimizu 890ddd
			m_imp->m_negativeThicknessPoints++;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	if (pos[count - 1].thick <= 0)
Toshihiro Shimizu 890ddd
		m_imp->m_negativeThicknessPoints++;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	invalidate();
Toshihiro Shimizu 890ddd
	//m_imp->computeBBox();
Toshihiro Shimizu 890ddd
	m_imp->computeParameterInControlPoint();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
double TStroke::getApproximateLength(double w0, double w1, double error) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_imp->computeCacheVector();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	assert((int)m_imp->m_partialLenghtArray.size() == getControlPointCount());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (w0 == w1)
Toshihiro Shimizu 890ddd
		return 0.0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	w0 = min(max(0.0, w0), 1.0);
Toshihiro Shimizu 890ddd
	w1 = min(max(0.0, w1), 1.0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (w0 > w1)
Toshihiro Shimizu 890ddd
		std::swap(w0, w1);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// vede se la lunghezza e' individuabile nella cache
Toshihiro Shimizu 890ddd
	if (0.0 == w0) {
Toshihiro Shimizu 890ddd
		vector<double>::iterator first;</double>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// trova l'iteratore alla prima posizione che risulta maggiore di w
Toshihiro Shimizu 890ddd
		first = std::upper_bound(
Toshihiro Shimizu 890ddd
			m_imp->m_parameterValueAtControlPoint.begin(),
Toshihiro Shimizu 890ddd
			m_imp->m_parameterValueAtControlPoint.end(),
Toshihiro Shimizu 890ddd
			w1 - TConsts::epsilon);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (first != m_imp->m_parameterValueAtControlPoint.end() &&
Toshihiro Shimizu 890ddd
			*first < w1 + TConsts::epsilon) {
Toshihiro Shimizu 890ddd
			int offset = distance(m_imp->m_parameterValueAtControlPoint.begin(), first);
Toshihiro Shimizu 890ddd
			return m_imp->m_partialLenghtArray[offset];
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int firstChunk, secondChunk;
Toshihiro Shimizu 890ddd
	double firstT, secondT;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// calcolo i chunk interessati ed i valori del parametro t
Toshihiro Shimizu 890ddd
	bool val1 = m_imp->retrieveChunkAndItsParamameter(w0, firstChunk, firstT);
Toshihiro Shimizu 890ddd
	assert(val1);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool val2 = m_imp->retrieveChunkAndItsParamameter(w1, secondChunk, secondT);
Toshihiro Shimizu 890ddd
	assert(val2);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (firstChunk == secondChunk)
Toshihiro Shimizu 890ddd
		return getChunk(firstChunk)->getApproximateLength(firstT, secondT, error);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double totalLength = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	totalLength += getChunk(firstChunk)->getApproximateLength(firstT, 1, error);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// lunghezza dei pezzi intermedi
Toshihiro Shimizu 890ddd
	for (int i = firstChunk + 1; i != secondChunk; i++)
Toshihiro Shimizu 890ddd
		totalLength += getChunk(i)->getApproximateLength(0.0, 1.0, error);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	totalLength += getChunk(secondChunk)->getApproximateLength(0.0, secondT, error);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return totalLength;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
double TStroke::getLength(double w0, double w1) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (w0 == w1)
Toshihiro Shimizu 890ddd
		return 0.0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//If necessary, swap values
Toshihiro Shimizu 890ddd
	w0 = min(max(0.0, w0), 1.0);
Toshihiro Shimizu 890ddd
	w1 = min(max(0.0, w1), 1.0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (w0 > w1)
Toshihiro Shimizu 890ddd
		std::swap(w0, w1);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Retrieve s1
Toshihiro Shimizu 890ddd
	int chunk;
Toshihiro Shimizu 890ddd
	double t;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool ok = !m_imp->retrieveChunkAndItsParamameter(w1, chunk, t);
Toshihiro Shimizu 890ddd
	assert(ok);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double s1 = getLength(chunk, t);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (w0 == 0.0)
Toshihiro Shimizu 890ddd
		return s1;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Retrieve s0
Toshihiro Shimizu 890ddd
	ok = !m_imp->retrieveChunkAndItsParamameter(w0, chunk, t);
Toshihiro Shimizu 890ddd
	assert(ok);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return s1 - getLength(chunk, t);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
double TStroke::getLength(int chunk, double t) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	//Compute length caches
Toshihiro Shimizu 890ddd
	m_imp->computeCacheVector();
Toshihiro Shimizu 890ddd
	assert((int)m_imp->m_partialLenghtArray.size() == getControlPointCount());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (t == 1.0)
Toshihiro Shimizu 890ddd
		++chunk, t = 0.0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double s = m_imp->m_partialLenghtArray[chunk << 1];
Toshihiro Shimizu 890ddd
	if (t > 0.0)
Toshihiro Shimizu 890ddd
		s += getChunk(chunk)->getLength(t);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return s;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TStroke::invalidate()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_imp->m_maxThickness = -1;
Toshihiro Shimizu 890ddd
	m_imp->m_isOutlineValid = false;
Toshihiro Shimizu 890ddd
	m_imp->m_isValidLength = false;
Toshihiro Shimizu 890ddd
	m_imp->m_flag = m_imp->m_flag | c_dirty_flag;
Toshihiro Shimizu 890ddd
	if (m_imp->m_prop)
Toshihiro Shimizu 890ddd
		m_imp->m_prop->notifyStrokeChange();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
/*! 
Toshihiro Shimizu 890ddd
N.B. Questa funzione e' piu' lenta rispetto alla insertCP
Toshihiro Shimizu 890ddd
perche' ricerca la posizione di s con un algoritmo di bisezione.
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
void TStroke::insertControlPointsAtLength(double s)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (0 > s || s > getLength())
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int chunk;
Toshihiro Shimizu 890ddd
	double t;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// cerca il cionco ed il parametro alla lunghezza s
Toshihiro Shimizu 890ddd
	if (!m_imp->retrieveChunkAndItsParamameterAtLength(s, chunk, t)) {
Toshihiro Shimizu 890ddd
		if (isAlmostZero(t) || areAlmostEqual(t, 1))
Toshihiro Shimizu 890ddd
			return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// calcolo i due "cionchi"
Toshihiro Shimizu 890ddd
		TThickQuadratic
Toshihiro Shimizu 890ddd
			*tqfirst = new TThickQuadratic,
Toshihiro Shimizu 890ddd
			*tqsecond = new TThickQuadratic;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		getChunk(chunk)->split(t, *tqfirst, *tqsecond);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		double parameterInStroke;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (0 == chunk)
Toshihiro Shimizu 890ddd
			parameterInStroke = m_imp->getW(2) * t;
Toshihiro Shimizu 890ddd
		else
Toshihiro Shimizu 890ddd
			parameterInStroke = t * m_imp->getW((chunk + 1) * 2) + (1 - t) * m_imp->getW(chunk * 2);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		m_imp->updateParameterValue(parameterInStroke, chunk, tqfirst, tqsecond);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// recupero la posizione nella lista delle curve
Toshihiro Shimizu 890ddd
		QuadStrokeChunkArray::iterator it = m_imp->m_centerLineArray.begin();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// elimino la curva vecchia
Toshihiro Shimizu 890ddd
		advance(it, chunk);
Toshihiro Shimizu 890ddd
		delete *it;
Toshihiro Shimizu 890ddd
		it = m_imp->m_centerLineArray.erase(it);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// ed aggiungo le nuove
Toshihiro Shimizu 890ddd
		it = m_imp->m_centerLineArray.insert(it, tqsecond);
Toshihiro Shimizu 890ddd
		it = m_imp->m_centerLineArray.insert(it, tqfirst);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	/* FAB
Toshihiro Shimizu 890ddd
#ifdef  _DEBUG
Toshihiro Shimizu 890ddd
  {
Toshihiro Shimizu 890ddd
    const int 
Toshihiro Shimizu 890ddd
      size = m_imp->m_parameterValueAtControlPoint.size();
Toshihiro Shimizu 890ddd
    double 
Toshihiro Shimizu 890ddd
      prev = m_imp->m_parameterValueAtControlPoint[0];
Toshihiro Shimizu 890ddd
    for( int i = 1;
Toshihiro Shimizu 890ddd
         i < size;
Toshihiro Shimizu 890ddd
         ++i )
Toshihiro Shimizu 890ddd
    {
Toshihiro Shimizu 890ddd
      assert( prev <= m_imp->m_parameterValueAtControlPoint[i] );
Toshihiro Shimizu 890ddd
      prev = m_imp->m_parameterValueAtControlPoint[i];
Toshihiro Shimizu 890ddd
    }
Toshihiro Shimizu 890ddd
  }
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
  //*/
Toshihiro Shimizu 890ddd
	invalidate();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TStroke::insertControlPoints(double w)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (0.0 > w || w > 1.0)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int chunk;
Toshihiro Shimizu 890ddd
	double tOfDivision = -1;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (m_imp->retrieveChunkAndItsParamameter(w, chunk, tOfDivision))
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (isAlmostZero(tOfDivision) || areAlmostEqual(tOfDivision, 1))
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	assert(0 <= chunk && chunk < getChunkCount());
Toshihiro Shimizu 890ddd
	assert(0 <= tOfDivision && tOfDivision <= 1.0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// calcolo i due "cionchi"
Toshihiro Shimizu 890ddd
	TThickQuadratic
Toshihiro Shimizu 890ddd
		*tqfirst = new TThickQuadratic,
Toshihiro Shimizu 890ddd
		*tqsecond = new TThickQuadratic;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	getChunk(chunk)->split(tOfDivision, *tqfirst, *tqsecond);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_imp->updateParameterValue(w, chunk, tqfirst, tqsecond);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// recupero la posizione nella lista delle curve
Toshihiro Shimizu 890ddd
	QuadStrokeChunkArray::iterator it = m_imp->m_centerLineArray.begin();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// elimino la curva vecchia
Toshihiro Shimizu 890ddd
	advance(it, chunk);
Toshihiro Shimizu 890ddd
	delete *it;
Toshihiro Shimizu 890ddd
	it = m_imp->m_centerLineArray.erase(it);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// ed aggiungo le nuove
Toshihiro Shimizu 890ddd
	it = m_imp->m_centerLineArray.insert(it, tqsecond);
Toshihiro Shimizu 890ddd
	m_imp->m_centerLineArray.insert(it, tqfirst);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	invalidate();
Toshihiro Shimizu 890ddd
	m_imp->computeCacheVector();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_imp->m_negativeThicknessPoints = 0;
Toshihiro Shimizu 890ddd
	for (UINT j = 0; j < m_imp->m_centerLineArray.size(); j++) {
Toshihiro Shimizu 890ddd
		if (m_imp->m_centerLineArray[j]->getThickP0().thick <= 0)
Toshihiro Shimizu 890ddd
			m_imp->m_negativeThicknessPoints++;
Toshihiro Shimizu 890ddd
		if (m_imp->m_centerLineArray[j]->getThickP1().thick <= 0)
Toshihiro Shimizu 890ddd
			m_imp->m_negativeThicknessPoints++;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	if (!m_imp->m_centerLineArray.empty() && m_imp->m_centerLineArray.back()->getThickP2().thick <= 0)
Toshihiro Shimizu 890ddd
		m_imp->m_negativeThicknessPoints++;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TStroke::reduceControlPoints(double error, vector<int> corners)</int>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	double step, quadLen;
Toshihiro Shimizu 890ddd
	vector<tthickpoint> tempVect, controlPoints;</tthickpoint>
Toshihiro Shimizu 890ddd
	TStroke *tempStroke = 0;
Toshihiro Shimizu 890ddd
	double missedLen = 0;
Toshihiro Shimizu 890ddd
	UINT cp, nextQuad, quadI, cornI, cpSize, size;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	const TThickQuadratic *quad = m_imp->m_centerLineArray.front();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	size = corners.size();
Toshihiro Shimizu 890ddd
	assert(size > 1);
Toshihiro Shimizu 890ddd
	if (size < 2) {
Toshihiro Shimizu 890ddd
		//Have at least the first and last stroke points as corners
Toshihiro Shimizu 890ddd
		corners.resize(2);
Toshihiro Shimizu 890ddd
		corners[0] = 0;
Toshihiro Shimizu 890ddd
		corners[1] = m_imp->m_centerLineArray.size();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//For every corners interval
Toshihiro Shimizu 890ddd
	for (cornI = 0; cornI < size - 1; ++cornI) {
Toshihiro Shimizu 890ddd
		tempVect.clear();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		nextQuad = corners[cornI + 1];
Toshihiro Shimizu 890ddd
		if (nextQuad > m_imp->m_centerLineArray.size()) {
Toshihiro Shimizu 890ddd
			assert(!"bad quadric index");
Toshihiro Shimizu 890ddd
			return;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		if (corners[cornI] >= (int)m_imp->m_centerLineArray.size()) {
Toshihiro Shimizu 890ddd
			assert(!"bad quadric index");
Toshihiro Shimizu 890ddd
			return;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		for (quadI = corners[cornI]; quadI < nextQuad; quadI++) {
Toshihiro Shimizu 890ddd
			quad = getChunk(quadI);
Toshihiro Shimizu 890ddd
			quadLen = quad->getLength();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			missedLen += quadLen;
Toshihiro Shimizu 890ddd
			if (quadLen && (missedLen > 1 || quadI == 0 || quadI == nextQuad - 1)) //err instead of 1?
Toshihiro Shimizu 890ddd
			{
Toshihiro Shimizu 890ddd
				missedLen = 0;
Toshihiro Shimizu 890ddd
				step = 1.0 / quadLen; //err instead of 1.0?
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				//si, lo so che t non e' lineare sulla lunghezza, ma secondo me funziona benissimo
Toshihiro Shimizu 890ddd
				//cosi'. tanto devo interpolare dei punto e non e' richiesto che siano a distanze
Toshihiro Shimizu 890ddd
				// simili. e poi difficilmete il punto p1 di una quadratica e' cosi' asimmetrico
Toshihiro Shimizu 890ddd
				for (double t = 0; t < 1.0; t += step)
Toshihiro Shimizu 890ddd
					tempVect.push_back(quad->getThickPoint(t));
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		tempVect.push_back(quad->getThickP2());
Toshihiro Shimizu 890ddd
		tempStroke = TStroke::interpolate(tempVect, error, false);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		cpSize = tempStroke->getControlPointCount();
Toshihiro Shimizu 890ddd
		for (cp = 0; cp < cpSize - 1; cp++) {
Toshihiro Shimizu 890ddd
			controlPoints.push_back(tempStroke->getControlPoint(cp));
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		delete tempStroke;
Toshihiro Shimizu 890ddd
		tempStroke = 0;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	controlPoints.push_back(m_imp->m_centerLineArray.back()->getThickP2());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#if _DEBUG
Toshihiro Shimizu 890ddd
	cpSize = controlPoints.size();
Toshihiro Shimizu 890ddd
	for (cp = 1; cp < cpSize; cp++)
Toshihiro Shimizu 890ddd
		assert(!(controlPoints[cp - 1] == controlPoints[cp]));
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	reshape(&(controlPoints[0]), controlPoints.size());
Toshihiro Shimizu 890ddd
	invalidate();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TStroke::reduceControlPoints(double error)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	vector<int> corners;</int>
Toshihiro Shimizu 890ddd
	corners.push_back(0);
Toshihiro Shimizu 890ddd
	detectCorners(this, 10, corners);
Toshihiro Shimizu 890ddd
	corners.push_back(getChunkCount());
Toshihiro Shimizu 890ddd
	reduceControlPoints(error, corners);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
double TStroke::getAverageThickness() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return m_imp->m_averageThickness;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
double TStroke::getMaxThickness()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (m_imp->m_maxThickness == -1)
Toshihiro Shimizu 890ddd
		m_imp->computeMaxThickness();
Toshihiro Shimizu 890ddd
	return m_imp->m_maxThickness;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TStroke::setAverageThickness(double thickness)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_imp->m_averageThickness = thickness;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool TStroke::operator==(const TStroke &s) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (getChunkCount() != s.getChunkCount())
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
	int i;
Toshihiro Shimizu 890ddd
	for (i = 0; i < getChunkCount(); i++) {
Toshihiro Shimizu 890ddd
		const TThickQuadratic *chanck = getChunk(i);
Toshihiro Shimizu 890ddd
		const TThickQuadratic *sChanck = s.getChunk(i);
Toshihiro Shimizu 890ddd
		if (chanck->getThickP0() != sChanck->getThickP0() ||
Toshihiro Shimizu 890ddd
			chanck->getThickP1() != sChanck->getThickP1() ||
Toshihiro Shimizu 890ddd
			chanck->getThickP2() != sChanck->getThickP2())
Toshihiro Shimizu 890ddd
			return false;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
int TStroke::getChunkCount() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return m_imp->getChunkCount();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
int TStroke::getControlPointCount() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return m_imp->getControlPointCount();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
const TThickQuadratic *TStroke::getChunk(int index) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return m_imp->getChunk(index);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TRectD TStroke::getBBox(double w0, double w1) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (w0 > w1)
Toshihiro Shimizu 890ddd
		tswap(w0, w1);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (w0 != 0.0 || w1 != 1.0)
Toshihiro Shimizu 890ddd
		return m_imp->computeSubBBox(w0, w1);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (m_imp->m_flag & c_dirty_flag)
Toshihiro Shimizu 890ddd
		((TStroke *)this)->computeBBox();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return m_imp->m_bBox;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TStroke::computeBBox()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_imp->m_bBox = TOutlineUtil::computeBBox(*this);
Toshihiro Shimizu 890ddd
	m_imp->m_flag &= ~c_dirty_flag;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TRectD TStroke::getCenterlineBBox() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return m_imp->computeCenterlineBBox();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TStroke::disableComputeOfCaches()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_imp->m_areDisabledComputeOfCaches = true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TStroke::enableComputeOfCaches()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_imp->m_areDisabledComputeOfCaches = false;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//DEL double TStroke::getDistance2(const   TPointD &p,
Toshihiro Shimizu 890ddd
//DEL                              double  maxDistance2,
Toshihiro Shimizu 890ddd
//DEL                              UINT    &chunkIndex,
Toshihiro Shimizu 890ddd
//DEL                              double  &currT)
Toshihiro Shimizu 890ddd
//DEL {
Toshihiro Shimizu 890ddd
//DEL   TRectD rect = getBBox();
Toshihiro Shimizu 890ddd
//DEL
Toshihiro Shimizu 890ddd
//DEL   if (!rect.contains(p))
Toshihiro Shimizu 890ddd
//DEL   {
Toshihiro Shimizu 890ddd
//DEL     double dist21 = tdistance2(p, rect.getP00());
Toshihiro Shimizu 890ddd
//DEL     double dist22 = tdistance2(p, rect.getP01());
Toshihiro Shimizu 890ddd
//DEL     double dist23 = tdistance2(p, rect.getP10());
Toshihiro Shimizu 890ddd
//DEL     double dist24 = tdistance2(p, rect.getP11());
Toshihiro Shimizu 890ddd
//DEL
Shinya Kitaoka 12c444
//DEL     if (std::min(dist21, dist22, dist23, dist24)>=maxDistance2)
Toshihiro Shimizu 890ddd
//DEL       return maxDistance2;
Toshihiro Shimizu 890ddd
//DEL   }
Toshihiro Shimizu 890ddd
//DEL
Toshihiro Shimizu 890ddd
//DEL   double distance2, curMaxDistance2=maxDistance2;
Toshihiro Shimizu 890ddd
//DEL
Toshihiro Shimizu 890ddd
//DEL   for (UINT i=0; i < m_imp->m_centerLineArray.size(); i++)
Toshihiro Shimizu 890ddd
//DEL   {
Toshihiro Shimizu 890ddd
//DEL     distance2 = getTQDistance2(*(m_imp->m_centerLineArray)[i], p, maxDistance2, currT);
Toshihiro Shimizu 890ddd
//DEL     if (distance2 < curMaxDistance2)
Toshihiro Shimizu 890ddd
//DEL     {
Toshihiro Shimizu 890ddd
//DEL       curMaxDistance2 = distance2;
Toshihiro Shimizu 890ddd
//DEL       chunkIndex = i;
Toshihiro Shimizu 890ddd
//DEL     }
Toshihiro Shimizu 890ddd
//DEL   }
Toshihiro Shimizu 890ddd
//DEL
Toshihiro Shimizu 890ddd
//DEL   return curMaxDistance2;
Toshihiro Shimizu 890ddd
//DEL }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TThickPoint TStroke::getThickPointAtLength(double s) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	assert(!m_imp->m_centerLineArray.empty());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (s <= 0)
Toshihiro Shimizu 890ddd
		return getControlPoint(0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (s >= getLength())
Toshihiro Shimizu 890ddd
		return getControlPoint(getControlPointCount() - 1);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int chunk;
Toshihiro Shimizu 890ddd
	double tOfDivision;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool error = m_imp->retrieveChunkAndItsParamameterAtLength(s, chunk, tOfDivision);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (error)
Toshihiro Shimizu 890ddd
		error = m_imp->retrieveChunkAndItsParamameterAtLength(s, chunk, tOfDivision);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	assert(!error);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (error)
Toshihiro Shimizu 890ddd
		return getControlPoint(0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return getChunk(chunk)->getThickPoint(tOfDivision);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TThickPoint TStroke::getThickPoint(double w) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	assert(!m_imp->m_centerLineArray.empty());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (w < 0)
Toshihiro Shimizu 890ddd
		return getControlPoint(0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (w > 1.0)
Toshihiro Shimizu 890ddd
		return getControlPoint(getControlPointCount() - 1);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int chunk = 0;
Toshihiro Shimizu 890ddd
	double t = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool error = m_imp->retrieveChunkAndItsParamameter(w, chunk, t);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	assert(!error);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (error)
Toshihiro Shimizu 890ddd
		return getControlPoint(0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return getChunk(chunk)->getThickPoint(t);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
double TStroke::getParameterAtLength(double s) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (s <= 0)
Toshihiro Shimizu 890ddd
		return 0;
Toshihiro Shimizu 890ddd
	else if (s >= getLength())
Toshihiro Shimizu 890ddd
		return 1;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int chunk;
Toshihiro Shimizu 890ddd
	double t;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!m_imp->retrieveChunkAndItsParamameterAtLength(s, chunk, t)) {
Toshihiro Shimizu 890ddd
		DoublePair p = m_imp->retrieveParametersFromChunk(chunk);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		return proportion(p.second, t, 1.0, p.first);
Toshihiro Shimizu 890ddd
	} else if (chunk < (int)getChunkCount() && t == -1)
Toshihiro Shimizu 890ddd
		return getParameterAtControlPoint(2 * chunk);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return 1.0;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
double TStroke::getParameterAtControlPoint(int n) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	double
Toshihiro Shimizu 890ddd
		out = -1;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (0 <= n &&
Toshihiro Shimizu 890ddd
		n < getControlPointCount())
Toshihiro Shimizu 890ddd
		out = m_imp->getW(n);
Toshihiro Shimizu 890ddd
	/* FAB
Toshihiro Shimizu 890ddd
  assert( 0.0 <= out &&
Toshihiro Shimizu 890ddd
          out <= 1.0 );
Toshihiro Shimizu 890ddd
  */
Toshihiro Shimizu 890ddd
	if (0.0 > out)
Toshihiro Shimizu 890ddd
		return 0.0;
Toshihiro Shimizu 890ddd
	if (out > 1.0)
Toshihiro Shimizu 890ddd
		return 1.0;
Toshihiro Shimizu 890ddd
	return out;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
double TStroke::getW(int chunkIndex, double t) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	DoublePair parRange = m_imp->retrieveParametersFromChunk(chunkIndex);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double w = proportion(parRange.second, t, 1.0, parRange.first);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	assert(0 <= w && w <= 1.0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return w;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
double TStroke::getW(const TPointD &p) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int chunkIndex;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double
Toshihiro Shimizu 890ddd
		tOfchunk,
Toshihiro Shimizu 890ddd
		distance2 = (numeric_limits<double>::max)();</double>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// cerca il chunk piu' vicino senza testare la BBox
Toshihiro Shimizu 890ddd
	getNearestChunk(p, tOfchunk, chunkIndex, distance2, false);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	assert(0 <= chunkIndex && chunkIndex <= getChunkCount());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	DoublePair parRange = m_imp->retrieveParametersFromChunk(chunkIndex);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double t = proportion(parRange.second, tOfchunk, 1.0, parRange.first);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	assert(0 <= t && t <= 1.0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return t;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool TStroke::getSpeedTwoValues(double w, TPointD &speed0, TPointD &speed1) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	bool ret = false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	assert(!m_imp->m_centerLineArray.empty());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (w < 0) {
Toshihiro Shimizu 890ddd
		speed0 = m_imp->m_centerLineArray.front()->getSpeed(0.0);
Toshihiro Shimizu 890ddd
		return ret;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (w > 1.0) {
Toshihiro Shimizu 890ddd
		speed0 = m_imp->m_centerLineArray.back()->getSpeed(1.0);
Toshihiro Shimizu 890ddd
		return ret;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int chunk;
Toshihiro Shimizu 890ddd
	double t;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool error = m_imp->retrieveChunkAndItsParamameter(w, chunk, t);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	assert(!error);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (error) {
Toshihiro Shimizu 890ddd
		speed0 = m_imp->m_centerLineArray.front()->getSpeed(0.0);
Toshihiro Shimizu 890ddd
		speed1 = -speed0;
Toshihiro Shimizu 890ddd
		return ret;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	speed0 = getChunk(chunk)->getSpeed(t);
Toshihiro Shimizu 890ddd
	speed1 = -speed0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (areAlmostEqual(t, 0.0, 1e-9) && chunk > 0 && (speed1 = -getChunk(chunk - 1)->getSpeed(1.0)) != -speed0)
Toshihiro Shimizu 890ddd
		ret = true;
Toshihiro Shimizu 890ddd
	else if (areAlmostEqual(t, 1.0, 1e-9) && chunk < getChunkCount() - 1 && (speed1 = -getChunk(chunk + 1)->getSpeed(0.0)) != -speed0) {
Toshihiro Shimizu 890ddd
		TPointD aux = -speed0;
Toshihiro Shimizu 890ddd
		speed0 = -speed1;
Toshihiro Shimizu 890ddd
		speed1 = aux;
Toshihiro Shimizu 890ddd
		ret = true;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (speed0 == TPointD()) //la quadratica e' degenere!!!
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		while (speed0 == TPointD()) {
Toshihiro Shimizu 890ddd
			speed0 = getChunk(chunk--)->getSpeed(1.0);
Toshihiro Shimizu 890ddd
			if (chunk <= 0)
Toshihiro Shimizu 890ddd
				break;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		chunk = 0;
Toshihiro Shimizu 890ddd
		while (speed0 == TPointD()) {
Toshihiro Shimizu 890ddd
			speed0 = getChunk(chunk++)->getSpeed(0.0);
Toshihiro Shimizu 890ddd
			if (chunk >= getChunkCount() - 1)
Toshihiro Shimizu 890ddd
				break;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (speed0 == TPointD()) {
Toshihiro Shimizu 890ddd
			if (getChunkCount() == 1) {
Toshihiro Shimizu 890ddd
				const TThickQuadratic *q = getChunk(0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				if (q->getP0() == q->getP1() &&
Toshihiro Shimizu 890ddd
					q->getP1() != q->getP2())
Toshihiro Shimizu 890ddd
					speed0 = TSegment(q->getP1(), q->getP2()).getSpeed(t);
Toshihiro Shimizu 890ddd
				else if (q->getP1() == q->getP2() &&
Toshihiro Shimizu 890ddd
						 q->getP0() != q->getP1())
Toshihiro Shimizu 890ddd
					speed0 = TSegment(q->getP0(), q->getP1()).getSpeed(t);
Toshihiro Shimizu 890ddd
				else
Toshihiro Shimizu 890ddd
					assert(speed0 != TPointD());
Toshihiro Shimizu 890ddd
			} else
Toshihiro Shimizu 890ddd
				assert(speed0 != TPointD());
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	return ret;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
TPointD TStroke::getSpeed(double w, bool outSpeed) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	assert(!m_imp->m_centerLineArray.empty());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (w < 0)
Toshihiro Shimizu 890ddd
		return m_imp->m_centerLineArray.front()->getSpeed(0.0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (w > 1.0)
Toshihiro Shimizu 890ddd
		return m_imp->m_centerLineArray.back()->getSpeed(1.0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int chunk;
Toshihiro Shimizu 890ddd
	double t;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool error = m_imp->retrieveChunkAndItsParamameter(w, chunk, t);
Toshihiro Shimizu 890ddd
	if (t == 1 && outSpeed && chunk < getChunkCount() - 1) {
Toshihiro Shimizu 890ddd
		chunk++;
Toshihiro Shimizu 890ddd
		t = 0;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	assert(!error);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (error)
Toshihiro Shimizu 890ddd
		return m_imp->m_centerLineArray.front()->getSpeed(0.0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TPointD speed = getChunk(chunk)->getSpeed(t);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (speed == TPointD()) //la quadratica e' degenere!!!
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		while (speed == TPointD()) {
Toshihiro Shimizu 890ddd
			speed = getChunk(chunk--)->getSpeed(1.0);
Toshihiro Shimizu 890ddd
			if (chunk <= 0)
Toshihiro Shimizu 890ddd
				break;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		chunk = 0;
Toshihiro Shimizu 890ddd
		while (speed == TPointD()) {
Toshihiro Shimizu 890ddd
			speed = getChunk(chunk++)->getSpeed(0.0);
Toshihiro Shimizu 890ddd
			if (chunk >= getChunkCount() - 1)
Toshihiro Shimizu 890ddd
				break;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		if (speed == TPointD()) {
Toshihiro Shimizu 890ddd
			if (getChunkCount() == 1) {
Toshihiro Shimizu 890ddd
				const TThickQuadratic *q = getChunk(0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				if (q->getP0() == q->getP1() &&
Toshihiro Shimizu 890ddd
					q->getP1() != q->getP2())
Toshihiro Shimizu 890ddd
					return TSegment(q->getP1(), q->getP2()).getSpeed(t);
Toshihiro Shimizu 890ddd
				else if (q->getP1() == q->getP2() &&
Toshihiro Shimizu 890ddd
						 q->getP0() != q->getP1())
Toshihiro Shimizu 890ddd
					return TSegment(q->getP0(), q->getP1()).getSpeed(t);
Toshihiro Shimizu 890ddd
				else
Toshihiro Shimizu 890ddd
					assert(speed != TPointD());
Toshihiro Shimizu 890ddd
			} else
Toshihiro Shimizu 890ddd
				assert(speed != TPointD());
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	return speed;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TPointD TStroke::getSpeedAtLength(double s) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	double t = getParameterAtLength(s);
Toshihiro Shimizu 890ddd
	return getSpeed(t);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
double TStroke::getLengthAtControlPoint(int n) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_imp->computeCacheVector();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (n >= getControlPointCount())
Toshihiro Shimizu 890ddd
		return m_imp->m_partialLenghtArray.back();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (n <= 0)
Toshihiro Shimizu 890ddd
		return m_imp->m_partialLenghtArray.front();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return m_imp->m_partialLenghtArray[n];
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TStroke::split(double w, TStroke &f, TStroke &s) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int chunk;
Toshihiro Shimizu 890ddd
	double t;
Toshihiro Shimizu 890ddd
	f.m_imp->m_maxThickness = -1;
Toshihiro Shimizu 890ddd
	s.m_imp->m_maxThickness = -1;
Toshihiro Shimizu 890ddd
	if (!m_imp->retrieveChunkAndItsParamameter(w, chunk, t)) {
Toshihiro Shimizu 890ddd
		assert(0 <= chunk && chunk < getChunkCount());
Toshihiro Shimizu 890ddd
		assert(0 <= w && w <= 1.0);
Toshihiro Shimizu 890ddd
		assert(0 <= t && t <= 1.0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		QuadStrokeChunkArray &chunkArray = m_imp->m_centerLineArray;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// build two temporary quadratic
Toshihiro Shimizu 890ddd
		TThickQuadratic
Toshihiro Shimizu 890ddd
			*tq1 = new TThickQuadratic,
Toshihiro Shimizu 890ddd
			*tq2 = new TThickQuadratic;
Toshihiro Shimizu 890ddd
		// make split
Toshihiro Shimizu 890ddd
		chunkArray[chunk]->split(t, *tq1, *tq2);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// a temporary vector of ThickQuadratic
Toshihiro Shimizu 890ddd
		QuadStrokeChunkArray vTQ;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// copy all chunk of stroke in a vTQ
Toshihiro Shimizu 890ddd
		int i;
Toshihiro Shimizu 890ddd
		for (i = 0; i < chunk; ++i)
Toshihiro Shimizu 890ddd
			vTQ.push_back(chunkArray[i]);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// not insert null length chunk (unless vTQ is empty....)
Toshihiro Shimizu 890ddd
		if (tq1->getLength() != 0.0 || w == 0.0 || vTQ.empty())
Toshihiro Shimizu 890ddd
			vTQ.push_back(tq1);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// build a temp and swap
Toshihiro Shimizu 890ddd
		TStroke *ts1 = TStroke::create(vTQ);
Toshihiro Shimizu 890ddd
		if (!ts1)
Toshihiro Shimizu 890ddd
			ts1 = new TStroke;
Toshihiro Shimizu 890ddd
		ts1->swapGeometry(f);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// clear vector (chunks are now under TStroke control)
Toshihiro Shimizu 890ddd
		vTQ.clear();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// idem...
Toshihiro Shimizu 890ddd
		if (tq2->getLength() != 0.0 || w == 1.0 || getChunkCount() == 0)
Toshihiro Shimizu 890ddd
			vTQ.push_back(tq2);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		for (i = chunk + 1; i < getChunkCount(); ++i)
Toshihiro Shimizu 890ddd
			vTQ.push_back(chunkArray[i]);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		TStroke *ts2 = TStroke::create(vTQ);
Toshihiro Shimizu 890ddd
		if (!ts2)
Toshihiro Shimizu 890ddd
			ts2 = new TStroke;
Toshihiro Shimizu 890ddd
		ts2->swapGeometry(s);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		//Copy style infos
Toshihiro Shimizu 890ddd
		f.setStyle(getStyle());
Toshihiro Shimizu 890ddd
		s.setStyle(getStyle());
Toshihiro Shimizu 890ddd
		f.outlineOptions() = s.outlineOptions() = outlineOptions();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		delete ts2;
Toshihiro Shimizu 890ddd
		delete ts1;
Toshihiro Shimizu 890ddd
		// delete temporary quadratic
Toshihiro Shimizu 890ddd
		delete tq1;
Toshihiro Shimizu 890ddd
		delete tq2;
Toshihiro Shimizu 890ddd
		if (f.getControlPointCount() == 3 && f.getControlPoint(0) != f.getControlPoint(2)) // gli stroke con solo 1 chunk vengono fatti dal tape tool...e devono venir riconosciuti come speciali di autoclose proprio dal fatto che hanno 1 solo chunk.
Toshihiro Shimizu 890ddd
			f.insertControlPoints(0.5);
Toshihiro Shimizu 890ddd
		if (s.getControlPointCount() == 3 && s.getControlPoint(0) != s.getControlPoint(2)) // gli stroke con solo 1 chunk vengono fatti dal tape tool...e devono venir riconosciuti come speciali di autoclose proprio dal fatto che hanno 1 solo chunk.
Toshihiro Shimizu 890ddd
			s.insertControlPoints(0.5);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TStroke::print(ostream &os) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	//m_imp->print(os);
Toshihiro Shimizu 890ddd
	const TThickQuadratic *q;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	os << "Punti di controllo\n";
Toshihiro Shimizu 890ddd
	for (int i = 0; i < getChunkCount(); ++i) {
Toshihiro Shimizu 890ddd
		os << "quad #" << i << ":" << endl;
Toshihiro Shimizu 890ddd
		q = getChunk(i);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		os << "    P0:" << q->getThickP0().x << ", " << q->getThickP0().y << ", " << q->getThickP0().thick << endl;
Toshihiro Shimizu 890ddd
		os << "    P1:" << q->getThickP1().x << ", " << q->getThickP1().y << ", " << q->getThickP1().thick << endl;
Toshihiro Shimizu 890ddd
		assert(i == getChunkCount() - 1 || (getChunk(i)->getThickP2() == getChunk(i + 1)->getThickP0()));
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	q = getChunk(getChunkCount() - 1);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	os << "    P2:" << q->getThickP2().x << ", " << q->getThickP2().y << ", " << q->getThickP2().thick << endl;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TStroke::transform(const TAffine &aff, bool doChangeThickness)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	for (UINT i = 0; i < m_imp->m_centerLineArray.size(); ++i) {
Toshihiro Shimizu 890ddd
		TThickQuadratic &ref = *m_imp->m_centerLineArray[i];
Toshihiro Shimizu 890ddd
		ref = transformQuad(aff, ref, doChangeThickness);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (doChangeThickness) {
Toshihiro Shimizu 890ddd
			double det = aff.det();
Toshihiro Shimizu 890ddd
			if (det == 0)
Toshihiro Shimizu 890ddd
				m_imp->m_negativeThicknessPoints = getControlPointCount();
Toshihiro Shimizu 890ddd
			if (m_imp->m_maxThickness != -1)
Toshihiro Shimizu 890ddd
				m_imp->m_maxThickness *= sqrt(fabs(det));
Toshihiro Shimizu 890ddd
			//else if(det<0)
Toshihiro Shimizu 890ddd
			//  m_imp->m_negativeThicknessPoints=getControlPointCount()-m_imp->m_negativeThicknessPoints;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	invalidate();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*
Toshihiro Shimizu 890ddd
void TStroke::draw(const TVectorRenderData &rd) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
  if(! m_imp->m_styleId)
Toshihiro Shimizu 890ddd
    return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
  TColorStyle * style = rd.m_palette->getStyle(m_imp->m_styleId);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
  if( !style->isStrokeStyle() || style->isEnabled() == false )
Toshihiro Shimizu 890ddd
    return;
Toshihiro Shimizu 890ddd
  
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
  if( !m_imp->m_prop || style != m_imp->m_prop->getColorStyle() )
Toshihiro Shimizu 890ddd
  {
Toshihiro Shimizu 890ddd
    delete m_imp->m_prop;
Toshihiro Shimizu 890ddd
    m_imp->m_prop = style->makeStrokeProp(this);  
Toshihiro Shimizu 890ddd
  }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
  m_imp->m_prop->draw(rd);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TStrokeProp *TStroke::getProp() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
#if DISEGNO_OUTLINE == 0
Toshihiro Shimizu 890ddd
	if (!m_imp->m_styleId)
Toshihiro Shimizu 890ddd
		return 0;
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	/*
Toshihiro Shimizu 890ddd
  TColorStyle * style = palette->getStyle(m_imp->m_styleId);
Toshihiro Shimizu 890ddd
  if( !style->isStrokeStyle() || style->isEnabled() == false )
Toshihiro Shimizu 890ddd
    return 0;
Toshihiro Shimizu 890ddd
  
Toshihiro Shimizu 890ddd
  if( !m_imp->m_prop || style != m_imp->m_prop->getColorStyle() )
Toshihiro Shimizu 890ddd
  {
Toshihiro Shimizu 890ddd
    delete m_imp->m_prop;
Toshihiro Shimizu 890ddd
    m_imp->m_prop = style->makeStrokeProp(this);  
Toshihiro Shimizu 890ddd
  }
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
	return m_imp->m_prop;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TStroke::setProp(TStrokeProp *prop)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	assert(prop);
Toshihiro Shimizu 890ddd
	delete m_imp->m_prop;
Toshihiro Shimizu 890ddd
	m_imp->m_prop = prop;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
int TStroke::getStyle() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return m_imp->m_styleId;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TStroke::setStyle(int styleId)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_imp->m_styleId = styleId;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	/*
Toshihiro Shimizu 890ddd
  if (!colorStyle || (colorStyle && colorStyle->isStrokeStyle())  )
Toshihiro Shimizu 890ddd
  {
Toshihiro Shimizu 890ddd
    m_imp->m_colorStyle = colorStyle;
Toshihiro Shimizu 890ddd
    delete m_imp->m_prop;
Toshihiro Shimizu 890ddd
    m_imp->m_prop = 0;
Toshihiro Shimizu 890ddd
  }
Toshihiro Shimizu 890ddd
  */
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TStroke &TStroke::changeDirection()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	UINT chunkCount = getChunkCount();
Toshihiro Shimizu 890ddd
	UINT to = tfloor(chunkCount * 0.5);
Toshihiro Shimizu 890ddd
	UINT i;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (chunkCount & 1)
Toshihiro Shimizu 890ddd
		changeTQDirection(m_imp->m_centerLineArray[to]);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	--chunkCount;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (i = 0; i < to; ++i) {
Toshihiro Shimizu 890ddd
		changeTQDirection(m_imp->m_centerLineArray[i]);
Toshihiro Shimizu 890ddd
		changeTQDirection(m_imp->m_centerLineArray[chunkCount - i]);
Toshihiro Shimizu 890ddd
		TThickQuadratic *q1 = m_imp->m_centerLineArray[i];
Toshihiro Shimizu 890ddd
		m_imp->m_centerLineArray[i] = m_imp->m_centerLineArray[chunkCount - i];
Toshihiro Shimizu 890ddd
		m_imp->m_centerLineArray[chunkCount - i] = q1;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	invalidate();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return *this;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TStroke::setFlag(TStrokeFlag flag, bool status)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (status)
Toshihiro Shimizu 890ddd
		m_imp->m_flag |= flag;
Toshihiro Shimizu 890ddd
	else
Toshihiro Shimizu 890ddd
		m_imp->m_flag &= ~flag;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool TStroke::getFlag(TStrokeFlag flag) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return (m_imp->m_flag & flag) != 0;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TStroke::swap(TStroke &ref)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	std::swap(m_imp, ref.m_imp);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Stroke props need to update their stroke owners
Toshihiro Shimizu 890ddd
	if (m_imp->m_prop)
Toshihiro Shimizu 890ddd
		m_imp->m_prop->setStroke(this);
Toshihiro Shimizu 890ddd
	if (ref.m_imp->m_prop)
Toshihiro Shimizu 890ddd
		ref.m_imp->m_prop->setStroke(&ref);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//The id is retained. This is coherent as the stroke id is supposedly
Toshihiro Shimizu 890ddd
	//not an exchangeable info.
Toshihiro Shimizu 890ddd
	std::swap(m_imp->m_id, ref.m_imp->m_id);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TStroke::swapGeometry(TStroke &ref)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_imp->swapGeometry(*ref.m_imp);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
int TStroke::getId() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return m_imp->m_id;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TStroke::setId(int id)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_imp->m_id = id;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//magari poi la sposto in un altro file
Toshihiro Shimizu 890ddd
TThickPoint TStroke::getCentroid() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	double totalLen = getLength();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (totalLen == 0)
Toshihiro Shimizu 890ddd
		return getControlPoint(0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double step = totalLen * 0.1;
Toshihiro Shimizu 890ddd
	double len = 0;
Toshihiro Shimizu 890ddd
	if (step > 10.0)
Toshihiro Shimizu 890ddd
		step = 10.0;
Toshihiro Shimizu 890ddd
	int count = 0;
Toshihiro Shimizu 890ddd
	TThickPoint point;
Toshihiro Shimizu 890ddd
	for (; len <= totalLen; len += step) {
Toshihiro Shimizu 890ddd
		count++;
Toshihiro Shimizu 890ddd
		point += getThickPointAtLength(len);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	return point * (1.0 / (double)count);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TStroke::setSelfLoop(bool loop)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (loop) {
Toshihiro Shimizu 890ddd
		// assert that a self loop is a stroke where first and last control points
Toshihiro Shimizu 890ddd
		// are the same
Toshihiro Shimizu 890ddd
		const int
Toshihiro Shimizu 890ddd
			cpCount = this->getControlPointCount();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		TThickPoint
Toshihiro Shimizu 890ddd
			p,
Toshihiro Shimizu 890ddd
			p0 = this->getControlPoint(0),
Toshihiro Shimizu 890ddd
			pn = this->getControlPoint(cpCount - 1);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		assert(areAlmostEqual(p0,
Toshihiro Shimizu 890ddd
							  pn,
Toshihiro Shimizu 890ddd
							  2));
Toshihiro Shimizu 890ddd
		p = (p0 + pn) * 0.5;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		this->setControlPoint(0,
Toshihiro Shimizu 890ddd
							  p);
Toshihiro Shimizu 890ddd
		this->setControlPoint(cpCount - 1,
Toshihiro Shimizu 890ddd
							  p);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	m_imp->m_selfLoop = loop;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool TStroke::isSelfLoop() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return m_imp->m_selfLoop;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool TStroke::isCenterLine() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	assert(m_imp->m_negativeThicknessPoints <= getControlPointCount());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return m_imp->m_negativeThicknessPoints == getControlPointCount();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TStroke::OutlineOptions &TStroke::outlineOptions()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return m_imp->m_outlineOptions;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
const TStroke::OutlineOptions &TStroke::outlineOptions() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return m_imp->m_outlineOptions;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
//  End Of File
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TStroke *joinStrokes(const TStroke *s0, const TStroke *s1)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TStroke *newStroke;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (s0 == s1) {
Toshihiro Shimizu 890ddd
		newStroke = new TStroke(*s0);
Toshihiro Shimizu 890ddd
		newStroke->setSelfLoop();
Toshihiro Shimizu 890ddd
		return newStroke;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	int i;
Toshihiro Shimizu 890ddd
	vector<tthickpoint> v;</tthickpoint>
Toshihiro Shimizu 890ddd
	for (i = 0; i < s0->getControlPointCount(); i++)
Toshihiro Shimizu 890ddd
		v.push_back(s0->getControlPoint(i));
Toshihiro Shimizu 890ddd
	if (areAlmostEqual(v.back(), s1->getControlPoint(0), 1e-3))
Toshihiro Shimizu 890ddd
		for (i = 1; i < s1->getControlPointCount(); i++)
Toshihiro Shimizu 890ddd
			v.push_back(s1->getControlPoint(i));
Toshihiro Shimizu 890ddd
	else if (areAlmostEqual(v.back(), s1->getControlPoint(s1->getControlPointCount() - 1), 1e-3))
Toshihiro Shimizu 890ddd
		for (i = s1->getControlPointCount() - 2; i >= 0; i--)
Toshihiro Shimizu 890ddd
			v.push_back(s1->getControlPoint(i));
Toshihiro Shimizu 890ddd
	else
Toshihiro Shimizu 890ddd
		assert(false);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	newStroke = new TStroke(v);
Toshihiro Shimizu 890ddd
	newStroke->setStyle(s0->getStyle());
Toshihiro Shimizu 890ddd
	newStroke->outlineOptions() = s0->outlineOptions();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return newStroke;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	/*
Toshihiro Shimizu 890ddd
  int cpCount1 = stroke1->getControlPointCount();
Toshihiro Shimizu 890ddd
  int cpCount2 = stroke2->getControlPointCount();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
  int qCount1 = stroke1->getChunkCount();
Toshihiro Shimizu 890ddd
  const TThickQuadratic* q1=stroke1->getChunk(qCount1-1 );
Toshihiro Shimizu 890ddd
  const TThickQuadratic* q2=stroke2->getChunk(0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
  TThickPoint extreme1 = q1->getThickP2() ;
Toshihiro Shimizu 890ddd
  TThickPoint extreme2 = q2->getThickP0();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
  vector<tthickpoint> points;</tthickpoint>
Toshihiro Shimizu 890ddd
  points.reserve(cpCount1+cpCount2-1);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
  int i =  0;
Toshihiro Shimizu 890ddd
  for(; i!=cpCount1-1; i++)
Toshihiro Shimizu 890ddd
    points.push_back( stroke1->getControlPoint(i));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
  if(extreme1==extreme2)
Toshihiro Shimizu 890ddd
  {
Toshihiro Shimizu 890ddd
    points.push_back(extreme1);
Toshihiro Shimizu 890ddd
  } 
Toshihiro Shimizu 890ddd
  else
Toshihiro Shimizu 890ddd
  {    
Toshihiro Shimizu 890ddd
    double len1=q1->getLength();
Toshihiro Shimizu 890ddd
    assert(len1>=0);
Toshihiro Shimizu 890ddd
    if(len1<=0)
Toshihiro Shimizu 890ddd
      len1=0;
Toshihiro Shimizu 890ddd
    double w1= exp(-len1*0.01);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
    double len2=q2->getLength();
Toshihiro Shimizu 890ddd
    assert(len2>=0);
Toshihiro Shimizu 890ddd
    if(len2<=0)
Toshihiro Shimizu 890ddd
      len2=0;
Toshihiro Shimizu 890ddd
    double w2= exp(-len2*0.01);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
    TThickPoint m1=q1->getThickP1();
Toshihiro Shimizu 890ddd
    TThickPoint m2=q2->getThickP1();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
    TThickPoint p1= extreme1*(1-w1)+m1*w1;
Toshihiro Shimizu 890ddd
    TThickPoint p2= extreme2*(1-w2)+m2*w2;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
    TThickPoint middleP= (p1 + p2)*0.5;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
    double angle=fabs(cross(normalize(m1-middleP),normalize(m2-middleP)));
Toshihiro Shimizu 890ddd
    if(  angle< 0.05)
Toshihiro Shimizu 890ddd
      middleP=(m1+m2)*0.5;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
    points.push_back(middleP);
Toshihiro Shimizu 890ddd
  }    
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
  for(i = 1; i!=cpCount2; i++)
Toshihiro Shimizu 890ddd
    points.push_back( stroke2->getControlPoint(i));
Toshihiro Shimizu 890ddd
  
Toshihiro Shimizu 890ddd
  newStroke = new TStroke(points);
Toshihiro Shimizu 890ddd
  newStroke->setStyle(stroke1->getStyle());
Toshihiro Shimizu 890ddd
  return newStroke;
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
namespace
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
int local_intersect(const TStroke &stroke,
Toshihiro Shimizu 890ddd
					const TSegment &segment,
Toshihiro Shimizu 890ddd
					std::vector<doublepair> &intersections,</doublepair>
Toshihiro Shimizu 890ddd
					bool strokeIsFirst)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	const TThickQuadratic *chunk;
Toshihiro Shimizu 890ddd
	for (int i = 0; i < stroke.getChunkCount(); i++) {
Toshihiro Shimizu 890ddd
		std::vector<doublepair> localIntersections;</doublepair>
Toshihiro Shimizu 890ddd
		chunk = stroke.getChunk(i);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (intersect(*chunk, segment, localIntersections)) {
Toshihiro Shimizu 890ddd
			for (UINT j = 0; j < localIntersections.size(); j++) {
Toshihiro Shimizu 890ddd
				double strokePar = localIntersections[j].first;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				strokePar = stroke.getW(chunk->getPoint(strokePar));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				// check for multiple solution
Toshihiro Shimizu 890ddd
				DoublePair
Toshihiro Shimizu 890ddd
					sol(strokeIsFirst ? strokePar : localIntersections[j].second,
Toshihiro Shimizu 890ddd
						strokeIsFirst ? localIntersections[j].second : strokePar);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				std::vector<doublepair>::iterator it_end = intersections.end();</doublepair>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				if (it_end == std::find(intersections.begin(), it_end, sol))
Toshihiro Shimizu 890ddd
					intersections.push_back(sol);
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	return intersections.size();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool almostOverlaps(const TRectD &r0, const TRectD &r1)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (r0.overlaps(r1))
Toshihiro Shimizu 890ddd
		return true;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if ((r0.x1 < r1.x0) && (areAlmostEqual(r0.x1, r1.x0, 1e-5)))
Toshihiro Shimizu 890ddd
		return true;
Toshihiro Shimizu 890ddd
	else if ((r1.x1 < r0.x0) && (areAlmostEqual(r1.x1, r0.x0, 1e-5)))
Toshihiro Shimizu 890ddd
		return true;
Toshihiro Shimizu 890ddd
	if ((r0.y1 < r1.y0) && (areAlmostEqual(r0.y1, r1.y0, 1e-5)))
Toshihiro Shimizu 890ddd
		return true;
Toshihiro Shimizu 890ddd
	else if ((r1.y1 < r0.y0) && (areAlmostEqual(r1.y1, r0.y0, 1e-5)))
Toshihiro Shimizu 890ddd
		return true;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return false;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool greaterThanOneAndLesserThanZero(double val)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (val > 1.0 || val < 0.0)
Toshihiro Shimizu 890ddd
		return true;
Toshihiro Shimizu 890ddd
	return false;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
int intersect(const TStroke *s1,
Toshihiro Shimizu 890ddd
			  const TStroke *s2,
Toshihiro Shimizu 890ddd
			  std::vector<doublepair> &intersections,</doublepair>
Toshihiro Shimizu 890ddd
			  bool checkBBox)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	UINT k = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	intersections.clear();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (checkBBox && !s1->getBBox().overlaps(s2->getBBox()))
Toshihiro Shimizu 890ddd
		return 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (int i = 0; i < s1->getChunkCount(); i++) {
Toshihiro Shimizu 890ddd
		const TQuadratic *q1 = s1->getChunk(i);
Toshihiro Shimizu 890ddd
		if (q1->getP0() == q1->getP2() && q1->getP1() == q1->getP2())
Toshihiro Shimizu 890ddd
			continue;
Toshihiro Shimizu 890ddd
		int j = 0;
Toshihiro Shimizu 890ddd
		if (s1 == s2) //this 'if': if after i-th stroke there are degenere strokes,
Toshihiro Shimizu 890ddd
					  //I do not consider them; so, instead of starting from j = i+2
Toshihiro Shimizu 890ddd
					  //I start from j = i+2+numDegeneres
Toshihiro Shimizu 890ddd
		{
Toshihiro Shimizu 890ddd
			j = i + 2;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			while (j <= s2->getChunkCount()) {
Toshihiro Shimizu 890ddd
				const TQuadratic *qAux = s2->getChunk(j - 1);
Toshihiro Shimizu 890ddd
				if (qAux->getP0() != qAux->getP2() || qAux->getP1() != qAux->getP2())
Toshihiro Shimizu 890ddd
					break;
Toshihiro Shimizu 890ddd
				j++;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		for (; j < s2->getChunkCount(); j++) {
Toshihiro Shimizu 890ddd
			const TQuadratic *q2 = s2->getChunk(j);
Toshihiro Shimizu 890ddd
			if (q2->getP0() == q2->getP2() && q2->getP1() == q2->getP2())
Toshihiro Shimizu 890ddd
				continue;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			if (!almostOverlaps(q1->getBBox(), q2->getBBox()))
Toshihiro Shimizu 890ddd
				continue;
Toshihiro Shimizu 890ddd
#ifdef CHECK_DEGLI_ESTREMI
Toshihiro Shimizu 890ddd
			vector<doublepair> quadIntersections1;</doublepair>
Toshihiro Shimizu 890ddd
			if (i == 0 || i == s1->getChunkCount() - 1) && (j==0 || j==s2->getChunkCount()-1))
Toshihiro Shimizu 890ddd
				{
Toshihiro Shimizu 890ddd
					TPointD pp1 = (i == 0 ? q1->getP0() : q1->getP2());
Toshihiro Shimizu 890ddd
					TPointD pp2 = (j == 0 ? q2->getP0() : q2->getP2());
Toshihiro Shimizu 890ddd
					if (areAlmostEqual(pp1, pp2)) {
Toshihiro Shimizu 890ddd
						intersections.push_back(DoublePair(i == 0 ? 0.0 : 1.0, j == 0 ? 0.0 : 1.0));
Toshihiro Shimizu 890ddd
						k++;
Toshihiro Shimizu 890ddd
						continue;
Toshihiro Shimizu 890ddd
					}
Toshihiro Shimizu 890ddd
					if (s1->getChunkCount() == 1 && s2->getChunkCount() == 1) {
Toshihiro Shimizu 890ddd
						TPointD pp1 = q1->getP2();
Toshihiro Shimizu 890ddd
						TPointD pp2 = q2->getP2();
Toshihiro Shimizu 890ddd
						if (areAlmostEqual(pp1, pp2)) {
Toshihiro Shimizu 890ddd
							intersections.push_back(DoublePair(1.0, 1.0));
Toshihiro Shimizu 890ddd
							k++;
Toshihiro Shimizu 890ddd
							continue;
Toshihiro Shimizu 890ddd
						}
Toshihiro Shimizu 890ddd
					}
Toshihiro Shimizu 890ddd
					if (s1->getChunkCount() == 1) {
Toshihiro Shimizu 890ddd
						TPointD pp1 = q1->getP2();
Toshihiro Shimizu 890ddd
						TPointD pp2 = (j == 0 ? q2->getP0() : q2->getP2());
Toshihiro Shimizu 890ddd
						if (areAlmostEqual(pp1, pp2)) {
Toshihiro Shimizu 890ddd
							intersections.push_back(DoublePair(1.0, j == 0 ? 0.0 : 1.0));
Toshihiro Shimizu 890ddd
							k++;
Toshihiro Shimizu 890ddd
							continue;
Toshihiro Shimizu 890ddd
						}
Toshihiro Shimizu 890ddd
					}
Toshihiro Shimizu 890ddd
					if (s2->getChunkCount() == 1) {
Toshihiro Shimizu 890ddd
						TPointD pp1 = (i == 0 ? q1->getP0() : q1->getP2());
Toshihiro Shimizu 890ddd
						TPointD pp2 = q2->getP2();
Toshihiro Shimizu 890ddd
						if (areAlmostEqual(pp1, pp2)) {
Toshihiro Shimizu 890ddd
							intersections.push_back(DoublePair(i == 0 ? 0.0 : 1.0, 1.0));
Toshihiro Shimizu 890ddd
							k++;
Toshihiro Shimizu 890ddd
							continue;
Toshihiro Shimizu 890ddd
						}
Toshihiro Shimizu 890ddd
					}
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			//if (j<s2->getChunkCount()-1)</s2->
Toshihiro Shimizu 890ddd
			//  {
Toshihiro Shimizu 890ddd
			//const TQuadratic *q3= s2->getChunk(j==0?0:j+1);
Toshihiro Shimizu 890ddd
			// evito di intersecare se le quadratiche sono uguali
Toshihiro Shimizu 890ddd
			if (*q1 == *q2 ||
Toshihiro Shimizu 890ddd
				(q1->getP0() == q2->getP2() && q1->getP1() == q2->getP1() && q1->getP2() == q2->getP0())) {
Toshihiro Shimizu 890ddd
				//j+=((j==0)?1:2);
Toshihiro Shimizu 890ddd
				continue;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
			//  }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			vector<doublepair> quadIntersections;</doublepair>
Toshihiro Shimizu 890ddd
			if (intersect(*q1, *q2, quadIntersections))
Toshihiro Shimizu 890ddd
				for (int h = 0; h < (int)quadIntersections.size(); h++) {
Toshihiro Shimizu 890ddd
					DoublePair res(getWfromChunkAndT(s1, i, quadIntersections[h].first),
Toshihiro Shimizu 890ddd
								   getWfromChunkAndT(s2, j, quadIntersections[h].second));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					if (areAlmostEqual(quadIntersections[h].first, 0) || areAlmostEqual(quadIntersections[h].first, 1) ||
Toshihiro Shimizu 890ddd
						areAlmostEqual(quadIntersections[h].second, 0) || areAlmostEqual(quadIntersections[h].second, 1)) {
Toshihiro Shimizu 890ddd
						int q = 0;
Toshihiro Shimizu 890ddd
						for (q = 0; q < (int)intersections.size(); q++)
Toshihiro Shimizu 890ddd
							if (areAlmostEqual(intersections[q].first, res.first, 1e-8) &&
Toshihiro Shimizu 890ddd
								areAlmostEqual(intersections[q].second, res.second, 1e-8))
Toshihiro Shimizu 890ddd
								break;
Toshihiro Shimizu 890ddd
						if (q < (int)intersections.size())
Toshihiro Shimizu 890ddd
							continue;
Toshihiro Shimizu 890ddd
					}
Toshihiro Shimizu 890ddd
					intersections.push_back(res);
Toshihiro Shimizu 890ddd
					//if (k==0 || intersections[k].first!=intersections[k-1].first || intersections[k].second!=intersections[k-1].second)
Toshihiro Shimizu 890ddd
					k++;
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	if (s1 == s2 && (s1->isSelfLoop() || s1->getPoint(0.0) == s1->getPoint(1.0))) {
Toshihiro Shimizu 890ddd
		int i;
Toshihiro Shimizu 890ddd
		for (i = 0; i < (int)intersections.size(); i++) {
Toshihiro Shimizu 890ddd
			assert(!(areAlmostEqual(intersections[i].first, 1.0, 1e-1) && areAlmostEqual(intersections[i].second, 0.0, 1e-1)));
Toshihiro Shimizu 890ddd
			if (areAlmostEqual(intersections[i].first, 0.0, 1e-1) && areAlmostEqual(intersections[i].second, 1.0, 1e-1))
Toshihiro Shimizu 890ddd
				break;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		if (i == (int)intersections.size()) {
Toshihiro Shimizu 890ddd
			intersections.push_back(DoublePair(0.0, 1.0));
Toshihiro Shimizu 890ddd
			k++;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return k;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
int intersect(const TSegment &segment,
Toshihiro Shimizu 890ddd
			  const TStroke &stroke,
Toshihiro Shimizu 890ddd
			  std::vector<doublepair> &intersections)</doublepair>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return local_intersect(stroke, segment, intersections, false);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
int intersect(const TStroke &stroke,
Toshihiro Shimizu 890ddd
			  const TSegment &segment,
Toshihiro Shimizu 890ddd
			  std::vector<doublepair> &intersections)</doublepair>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return local_intersect(stroke, segment, intersections, true);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
int intersect(const TStroke &stroke,
Toshihiro Shimizu 890ddd
			  const TPointD ¢er,
Toshihiro Shimizu 890ddd
			  double radius,
Toshihiro Shimizu 890ddd
			  vector<double> &intersections)</double>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	//            2    2    2
Toshihiro Shimizu 890ddd
	// riconduco x  + y  = r  con x(t) y(t) alla forma
Toshihiro Shimizu 890ddd
	//        2                2           2              2    2
Toshihiro Shimizu 890ddd
	// ( a_x t + b_x t + c_x  ) + ( a_y t + b_y t + c_y  )  = r
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//     2
Toshihiro Shimizu 890ddd
	//  a x  + b x + c
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	const int a = 2;
Toshihiro Shimizu 890ddd
	const int b = 1;
Toshihiro Shimizu 890ddd
	const int c = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	vector<tpointd> bez(3);</tpointd>
Toshihiro Shimizu 890ddd
	vector<tpointd> pol(3);</tpointd>
Toshihiro Shimizu 890ddd
	vector<double> coeff(5);</double>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (int chunk = 0; chunk < stroke.getChunkCount(); ++chunk) {
Toshihiro Shimizu 890ddd
		const TThickQuadratic *tq = stroke.getChunk(chunk);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		bez[0] = tq->getP0();
Toshihiro Shimizu 890ddd
		bez[1] = tq->getP1();
Toshihiro Shimizu 890ddd
		bez[2] = tq->getP2();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		bezier2poly(bez, pol);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		pol[c] -= center;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		coeff[4] = sq(pol[a].x) + sq(pol[a].y);
Toshihiro Shimizu 890ddd
		coeff[3] = 2.0 * (pol[a].x * pol[b].x + pol[a].y * pol[b].y);
Toshihiro Shimizu 890ddd
		coeff[2] = 2.0 * (pol[a].x * pol[c].x + pol[a].y * pol[c].y) + sq(pol[b].x) + sq(pol[b].y);
Toshihiro Shimizu 890ddd
		coeff[1] = 2.0 * (pol[b].x * pol[c].x + pol[b].y * pol[c].y);
Toshihiro Shimizu 890ddd
		coeff[0] = sq(pol[c].x) + sq(pol[c].y) - sq(radius);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		vector<double> sol;</double>
Toshihiro Shimizu 890ddd
		rootFinding(coeff, sol);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		sol.erase(remove_if(sol.begin(),
Toshihiro Shimizu 890ddd
							sol.end(),
Toshihiro Shimizu 890ddd
							greaterThanOneAndLesserThanZero),
Toshihiro Shimizu 890ddd
				  sol.end());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		for (UINT j = 0; j < sol.size(); ++j)
Toshihiro Shimizu 890ddd
			intersections.push_back(getWfromChunkAndT(&stroke, chunk, sol[j]));
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#if defined(DEBUG) || defined(_DEBUG)
Toshihiro Shimizu 890ddd
	/*
Toshihiro Shimizu 890ddd
  cout<<"interesections:";
Toshihiro Shimizu 890ddd
  copy( intersections.begin(), intersections.end(), ostream_iterator<double>( cout, " " ) );</double>
Toshihiro Shimizu 890ddd
  cout<
Toshihiro Shimizu 890ddd
  */
Toshihiro Shimizu 890ddd
	// assert to test intersections are not decrescent
Toshihiro Shimizu 890ddd
	vector<double> test;</double>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	adjacent_difference(intersections.begin(), intersections.end(), back_inserter(test));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	while (!test.empty()) {
Toshihiro Shimizu 890ddd
		assert(test.back() >= 0);
Toshihiro Shimizu 890ddd
		test.pop_back();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return intersections.size();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void splitStroke(const TStroke &tq,
Toshihiro Shimizu 890ddd
				 const vector<double> &pars,</double>
Toshihiro Shimizu 890ddd
				 std::vector<tstroke *=""> &v)</tstroke>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (pars.empty())
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	UINT
Toshihiro Shimizu 890ddd
		i,
Toshihiro Shimizu 890ddd
		vSize = pars.size();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	vector<double> length(vSize);</double>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// primo passo estraggo i parametri di lunghezza
Toshihiro Shimizu 890ddd
	for (i = 0; i < vSize; ++i)
Toshihiro Shimizu 890ddd
		length[i] = tq.getLength(pars[i]);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	std::adjacent_difference(length.begin(), length.end(), length.begin());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TStroke *q1, q2, q3;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	q1 = new TStroke();
Toshihiro Shimizu 890ddd
	tq.split(pars[0], *q1, q2);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	assert(areAlmostEqual(q1->getLength(), length[0], 1e-4));
Toshihiro Shimizu 890ddd
	v.push_back(q1);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (i = 1; i < vSize; ++i) {
Toshihiro Shimizu 890ddd
		q1 = new TStroke();
Toshihiro Shimizu 890ddd
		double par = q2.getParameterAtLength(length[i]);
Toshihiro Shimizu 890ddd
		assert(0 <= par && par <= 1.0);
Toshihiro Shimizu 890ddd
		q2.split(par, *q1, q3);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		assert(areAlmostEqual(q1->getLength(), length[i], 1e-4));
Toshihiro Shimizu 890ddd
		v.push_back(q1);
Toshihiro Shimizu 890ddd
		q2 = q3;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	v.push_back(new TStroke(q2));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void detectCorners(const TStroke *stroke, double minDegree, std::vector<int> &corners)</int>
Toshihiro Shimizu 890ddd
{
Shinya Kitaoka ee259f
	const double minSin = fabs(sin(minDegree * M_PI_180));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	const TThickQuadratic *quad1 = 0;
Toshihiro Shimizu 890ddd
	const TThickQuadratic *quad2 = 0;
Toshihiro Shimizu 890ddd
	UINT quadCount1 = stroke->getChunkCount();
Toshihiro Shimizu 890ddd
	TPointD speed1, speed2;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TPointD tan1, tan2;
Toshihiro Shimizu 890ddd
	quad1 = stroke->getChunk(0);
Toshihiro Shimizu 890ddd
	for (UINT j = 1; j < quadCount1; j++) {
Toshihiro Shimizu 890ddd
		quad2 = stroke->getChunk(j);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		speed1 = quad1->getSpeed(1);
Toshihiro Shimizu 890ddd
		speed2 = quad2->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
			if (tan1 * tan2 < 0 || fabs(cross(tan1, tan2)) >= minSin)
Toshihiro Shimizu 890ddd
				corners.push_back(j);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		quad1 = quad2;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
namespace
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//! Rimuove le quadratiche nulle, cioe' i chunk in cui i TThickPoint sono quasi uguali
Toshihiro Shimizu 890ddd
bool removeNullQuadratic(TStroke *stroke, bool checkThickness = true)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	vector<tthickpoint> points;</tthickpoint>
Toshihiro Shimizu 890ddd
	UINT i, qCount = stroke->getChunkCount();
Toshihiro Shimizu 890ddd
	const TThickQuadratic *q;
Toshihiro Shimizu 890ddd
	TThickPoint p1, p2, p3;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//se i punti coincidono e' una stroke puntiforme ed e' ammessa
Toshihiro Shimizu 890ddd
	if (qCount == 1)
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool check = false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (i = 0; i != qCount; i++) {
Toshihiro Shimizu 890ddd
		q = stroke->getChunk(i);
Toshihiro Shimizu 890ddd
		p1 = q->getThickP0();
Toshihiro Shimizu 890ddd
		p2 = q->getThickP1();
Toshihiro Shimizu 890ddd
		p3 = q->getThickP2();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (areAlmostEqual(p1.x, p2.x) && areAlmostEqual(p2.x, p3.x) &&
Toshihiro Shimizu 890ddd
			areAlmostEqual(p1.y, p2.y) && areAlmostEqual(p2.y, p3.y) &&
Toshihiro Shimizu 890ddd
			(!checkThickness ||
Toshihiro Shimizu 890ddd
			 (areAlmostEqual(p1.thick, p2.thick) && areAlmostEqual(p2.thick, p3.thick)))) {
Toshihiro Shimizu 890ddd
			//assert(!"null quadratic");
Toshihiro Shimizu 890ddd
			check = true;
Toshihiro Shimizu 890ddd
		} else {
Toshihiro Shimizu 890ddd
			points.push_back(p1);
Toshihiro Shimizu 890ddd
			points.push_back(p2);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (check) {
Toshihiro Shimizu 890ddd
		points.push_back(p3);
Toshihiro Shimizu 890ddd
		stroke->reshape(&(points[0]), points.size());
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return check;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//! Converte un TThickPoint p0 in un T3DPoint
Toshihiro Shimizu 890ddd
inline T3DPointD thickPntTo3DPnt(const TThickPoint &p0)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return T3DPointD(p0.x, p0.y, p0.thick);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//! Converte un vettore di TThickPoint from in un vettore di T3DPointD to
Toshihiro Shimizu 890ddd
void convert(const vector<tthickpoint> &from, vector<t3dpointd> &to)</t3dpointd></tthickpoint>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	to.resize(from.size());
Toshihiro Shimizu 890ddd
	transform(from.begin(), from.end(), to.begin(), thickPntTo3DPnt);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
typedef vector<tthickcubic *=""> TThickCubicArray;</tthickcubic>
Toshihiro Shimizu 890ddd
typedef vector<tthickquadratic *=""> QuadStrokeChunkArray;</tthickquadratic>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*! 
Toshihiro Shimizu 890ddd
	  Restituisce un puntatore ad un array di double che contiene la distanza tra
Toshihiro Shimizu 890ddd
		il primo punto e i successivi diviso la distanza tra il primo punto e l'ultimo
Toshihiro Shimizu 890ddd
		*/
Toshihiro Shimizu 890ddd
double *chordLengthParameterize3D(const T3DPointD *pointsArrayBegin,
Toshihiro Shimizu 890ddd
								  int size)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	double *u = new double[size];
Toshihiro Shimizu 890ddd
	u[0] = 0.0;
Toshihiro Shimizu 890ddd
	int i;
Toshihiro Shimizu 890ddd
	for (i = 1; i < size; i++)
Toshihiro Shimizu 890ddd
		u[i] = u[i - 1] + tdistance(*(pointsArrayBegin + i), *(pointsArrayBegin + i - 1));
Toshihiro Shimizu 890ddd
	for (i = 1; i < size; i++) {
Toshihiro Shimizu 890ddd
		assert(!isAlmostZero(u[size - 1]));
Toshihiro Shimizu 890ddd
		u[i] = u[i] / u[size - 1];
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	return u;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*!
Toshihiro Shimizu 890ddd
    Returns a \a measure of the maximal discrepancy of the points specified
Toshihiro Shimizu 890ddd
    by pointsArray from the corresponding cubic(u[]) points.
Toshihiro Shimizu 890ddd
  */
Toshihiro Shimizu 890ddd
double computeMaxError3D(const TThickCubic &cubic,
Toshihiro Shimizu 890ddd
						 const T3DPointD *pointsArrayBegin,
Toshihiro Shimizu 890ddd
						 int size,
Toshihiro Shimizu 890ddd
						 double *u,
Toshihiro Shimizu 890ddd
						 int &splitPoint)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	double err, maxErr = 0;
Toshihiro Shimizu 890ddd
	splitPoint = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (int i = 1; i < size - 1; i++) {
Toshihiro Shimizu 890ddd
#ifdef USE_NEW_3D_ERROR_COMPUTE
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		//Being cubic a THICK cubic, we assume that the supplied points' z
Toshihiro Shimizu 890ddd
		//refers to thicknesses as well.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		//So, given 2 thick points in the plane, we use the maximal distance
Toshihiro Shimizu 890ddd
		//of 'corresponding' outline points. Correspondence refers to the
Toshihiro Shimizu 890ddd
		//same relative position from centers. It's easily verifiable that
Toshihiro Shimizu 890ddd
		//such maximal distance is found when the relative positions both lie
Toshihiro Shimizu 890ddd
		//along the line connecting the two centers.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		const TThickPoint &A(cubic.getThickPoint(u[i]));
Toshihiro Shimizu 890ddd
		const T3DPointD &B(pointsArrayBegin[i]);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		err = sqrt(sq(B.x - A.x) + sq(B.y - A.y)) + fabs(B.z - A.thick);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#else
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		//Old version, less intuitive. Similar to the above, except that the 2d-norm is
Toshihiro Shimizu 890ddd
		//roughly multiplied by  norm((TPointD) B-A) / A.thick      ... I wonder why ....
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		T3DPointD delta = thickPntTo3DPnt(cubic.getThickPoint(u[i])) - *(pointsArrayBegin + i);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		double thick = cubic.getThickPoint(u[i]).thick;
Toshihiro Shimizu 890ddd
		if (thick <= 2.0)
Toshihiro Shimizu 890ddd
			thick = 2.0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		err = norm2(TPointD(delta.x, delta.y)) / thick;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (fabs(delta.z) > 2.0)
Toshihiro Shimizu 890ddd
			err = err + fabs(delta.z);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (err >= maxErr) {
Toshihiro Shimizu 890ddd
			maxErr = err;
Toshihiro Shimizu 890ddd
			splitPoint = i;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return maxErr;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
double NewtonRaphsonRootFind3D(const TThickCubic &cubic, const T3DPointD &p3D, double u)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TPointD qU = cubic.getPoint(u);
Toshihiro Shimizu 890ddd
	TPointD q1U = cubic.getSpeed(u);
Toshihiro Shimizu 890ddd
	TPointD q2U = cubic.getAcceleration(u);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TPointD p(p3D.x, p3D.y);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return u - ((qU - p) * q1U) / (norm2(q1U) + (qU - p) * q2U);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
int compareDouble(const void *e1, const void *e2)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return (*(double *)e1 < *(double *)e2) ? -1 : (*(double *)e1 == *(double *)e2) ? 0 : 1;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
//! Ricalcola i valori di u[] sulla base del metodo di Newton Raphson
Toshihiro Shimizu 890ddd
double *reparameterize3D(const TThickCubic &cubic,
Toshihiro Shimizu 890ddd
						 const T3DPointD *pointsArrayBegin,
Toshihiro Shimizu 890ddd
						 int size,
Toshihiro Shimizu 890ddd
						 double *u)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	double *uPrime = new double[size];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (int i = 0; i < size; i++) {
Toshihiro Shimizu 890ddd
		uPrime[i] = NewtonRaphsonRootFind3D(cubic, *(pointsArrayBegin + i), u[i]);
Toshihiro Shimizu 890ddd
		if (!_finite(uPrime[i])) {
Toshihiro Shimizu 890ddd
			delete uPrime;
Toshihiro Shimizu 890ddd
			return 0;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	qsort(uPrime, size, sizeof(double), compareDouble);
Toshihiro Shimizu 890ddd
	//std::sort( uPrime, uPrime+size );
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (uPrime[0] < 0.0 || uPrime[size - 1] > 1.0) {
Toshihiro Shimizu 890ddd
		delete uPrime;
Toshihiro Shimizu 890ddd
		return 0;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	assert(uPrime[0] >= 0.0);
Toshihiro Shimizu 890ddd
	assert(uPrime[size - 1] <= 1.0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return uPrime;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
inline double B1(double u)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	double tmp = 1.0 - u;
Toshihiro Shimizu 890ddd
	return 3 * u * tmp * tmp;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
inline double B2(double u)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return 3 * u * u * (1 - u);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
inline double B0plusB1(double u)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	double tmp = 1.0 - u;
Toshihiro Shimizu 890ddd
	return tmp * tmp * (1.0 + 2.0 * u);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
inline double B2plusB3(double u)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return u * u * (3.0 - 2.0 * u);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
} // end of unnamed namespace
Toshihiro Shimizu 890ddd
  //-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//! Classe che definisce uno stroke cubico
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class TCubicStroke
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
private:
Toshihiro Shimizu 890ddd
	//! Genera un TThickCubic
Toshihiro Shimizu 890ddd
	TThickCubic *generateCubic3D(const T3DPointD pointsArrayBegin[],
Toshihiro Shimizu 890ddd
								 const double uPrime[],
Toshihiro Shimizu 890ddd
								 int size,
Toshihiro Shimizu 890ddd
								 const T3DPointD &tangentLeft,
Toshihiro Shimizu 890ddd
								 const T3DPointD &tangentRight);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//! Genera una cubica in modo ricorsivo
Toshihiro Shimizu 890ddd
	void fitCubic3D(const T3DPointD pointsArrayBegin[],
Toshihiro Shimizu 890ddd
					int size,
Toshihiro Shimizu 890ddd
					const T3DPointD &tangentLeft,
Toshihiro Shimizu 890ddd
					const T3DPointD &tangentRight,
Toshihiro Shimizu 890ddd
					double error);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//! Rettangolo che contiene il TCubicStroke
Toshihiro Shimizu 890ddd
	TRectD m_bBox;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	//! Puntatore a vettore di puntatori a TThickCubic
Toshihiro Shimizu 890ddd
	vector<tthickcubic *=""> *m_cubicChunkArray;</tthickcubic>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//! Costruttore
Toshihiro Shimizu 890ddd
	TCubicStroke();
Toshihiro Shimizu 890ddd
	//! Costruttore
Toshihiro Shimizu 890ddd
	/*!
Toshihiro Shimizu 890ddd
		  Costruisce un TCubicStroke uguale al TCubicStroke datogli
Toshihiro Shimizu 890ddd
		  */
Toshihiro Shimizu 890ddd
	TCubicStroke(const TCubicStroke &stroke);
Toshihiro Shimizu 890ddd
	//! Costruttore
Toshihiro Shimizu 890ddd
	/*!
Toshihiro Shimizu 890ddd
		  Costruisce un TCubicStroke da un array di T3DPointD,
Toshihiro Shimizu 890ddd
		  in funzione dei due parametri error e doDetectCorners
Toshihiro Shimizu 890ddd
		  */
Toshihiro Shimizu 890ddd
	TCubicStroke(const vector<t3dpointd> &pointsArray3D,</t3dpointd>
Toshihiro Shimizu 890ddd
				 double error, bool doDetectCorners = true);
Toshihiro Shimizu 890ddd
	/*
Toshihiro Shimizu 890ddd
      TCubicStroke(       vector<tpointd> &pointsArray, </tpointd>
Toshihiro Shimizu 890ddd
      double          error, 
Toshihiro Shimizu 890ddd
      const TPointD         &tangentLeft, 
Toshihiro Shimizu 890ddd
      const TPointD         &tangentRight);
Toshihiro Shimizu 890ddd
    */
Toshihiro Shimizu 890ddd
	//! Distruttore
Toshihiro Shimizu 890ddd
	~TCubicStroke();
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
namespace
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// It implements the degree reduction algorithm, returning the times
Toshihiro Shimizu 890ddd
// that the cubic must be splitted (in the half), in order to approximate
Toshihiro Shimizu 890ddd
// it with a sequence of quadratic bezier curves.
Toshihiro Shimizu 890ddd
// This method doesn't take into count the thickness of the control points,
Toshihiro Shimizu 890ddd
// so it just operates on the center line of the fat cubic curve
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*! It splits a cubic bezier curve 'splits' times in the half. Then each
Toshihiro Shimizu 890ddd
      subcurve is converted into quadratic curve, computing the middle control
Toshihiro Shimizu 890ddd
      circle as the weighted averege of the four control circles of the
Toshihiro Shimizu 890ddd
      original cubic subcurve.
Toshihiro Shimizu 890ddd
  */
Toshihiro Shimizu 890ddd
void doComputeQuadraticsFromCubic(const TThickCubic &cubic,
Toshihiro Shimizu 890ddd
								  int splits,
Toshihiro Shimizu 890ddd
								  vector<tthickquadratic *=""> &chunkArray)</tthickquadratic>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TThickPoint p0r, p1r, p2r, p3r, p0l, p1l, p2l, p3l;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	p0l = cubic.getThickP0();
Toshihiro Shimizu 890ddd
	p1l = cubic.getThickP1();
Toshihiro Shimizu 890ddd
	p2l = cubic.getThickP2();
Toshihiro Shimizu 890ddd
	p3l = cubic.getThickP3();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	p3l = 0.5 * (p3l + p2l);
Toshihiro Shimizu 890ddd
	p2l = 0.5 * (p2l + p1l);
Toshihiro Shimizu 890ddd
	p1l = 0.5 * (p1l + p0l);
Toshihiro Shimizu 890ddd
	p3l = 0.5 * (p3l + p2l);
Toshihiro Shimizu 890ddd
	p2l = 0.5 * (p2l + p1l);
Toshihiro Shimizu 890ddd
	p3l = 0.5 * (p3l + p2l);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//  cubic.getControlPoints(p0r, p1r, p2r, p3r);
Toshihiro Shimizu 890ddd
	p0r = cubic.getThickP0();
Toshihiro Shimizu 890ddd
	p1r = cubic.getThickP1();
Toshihiro Shimizu 890ddd
	p2r = cubic.getThickP2();
Toshihiro Shimizu 890ddd
	p3r = cubic.getThickP3();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	p0r = 0.5 * (p0r + p1r);
Toshihiro Shimizu 890ddd
	p1r = 0.5 * (p1r + p2r);
Toshihiro Shimizu 890ddd
	p2r = 0.5 * (p2r + p3r);
Toshihiro Shimizu 890ddd
	p0r = 0.5 * (p0r + p1r);
Toshihiro Shimizu 890ddd
	p1r = 0.5 * (p1r + p2r);
Toshihiro Shimizu 890ddd
	p0r = 0.5 * (p0r + p1r);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (splits > 0) {
Toshihiro Shimizu 890ddd
		TThickCubic cubic1(cubic);
Toshihiro Shimizu 890ddd
		TThickCubic tmp_1(p0l, p1l, p2l, p3l);
Toshihiro Shimizu 890ddd
		std::swap(cubic1, tmp_1);
Toshihiro Shimizu 890ddd
		doComputeQuadraticsFromCubic(cubic1, splits - 1, chunkArray);
Toshihiro Shimizu 890ddd
		TThickCubic tmp_2(p0r, p1r, p2r, p3r);
Toshihiro Shimizu 890ddd
		std::swap(cubic1, tmp_2);
Toshihiro Shimizu 890ddd
		doComputeQuadraticsFromCubic(cubic1, splits - 1, chunkArray);
Toshihiro Shimizu 890ddd
	} else {
Toshihiro Shimizu 890ddd
		TThickQuadratic *chunkL = new TThickQuadratic(p0l, 0.25 * (3 * (p1l + p2l) - (p0l + p3l)), p3l);
Toshihiro Shimizu 890ddd
		TThickQuadratic *chunkR = new TThickQuadratic(p0r, 0.25 * (3 * (p1r + p2r) - (p0r + p3r)), p3r);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// int size = chunkArray.size();
Toshihiro Shimizu 890ddd
		chunkArray.push_back(chunkL);
Toshihiro Shimizu 890ddd
		chunkArray.push_back(chunkR);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*!
Toshihiro Shimizu 890ddd
	  Genera una o piu' quadratiche da una cubica.
Toshihiro Shimizu 890ddd
    Pone una serie di condizioni , se sono verificate crea una unica quadratica,
Toshihiro Shimizu 890ddd
		altrimenti richiama doComputeQuadraticsFromCubic
Toshihiro Shimizu 890ddd
	  */
Toshihiro Shimizu 890ddd
void computeQuadraticsFromCubic(const TThickCubic &cubic,
Toshihiro Shimizu 890ddd
								double error,
Toshihiro Shimizu 890ddd
								vector<tthickquadratic *=""> &chunkArray)</tthickquadratic>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	const double T = 0.21132486540518711775; /* 1/2 - sqrt(3)/6 */
Toshihiro Shimizu 890ddd
	const double S = (1 - T);
Toshihiro Shimizu 890ddd
	int splits;
Toshihiro Shimizu 890ddd
	double dist2 = tdistance2(cubic.getP1(), cubic.getP2());
Toshihiro Shimizu 890ddd
	if (dist2 < 2) {
Toshihiro Shimizu 890ddd
		chunkArray.push_back(new TThickQuadratic(cubic.getThickP0(), 0.5 * (cubic.getThickP1() + cubic.getThickP2()), cubic.getThickP3()));
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TPointD dp = ((S * S * S) - (S * S - S * T / 2)) * cubic.getP0() +
Toshihiro Shimizu 890ddd
				 ((3 * S * S * T) - (S * T * 3 / 2)) * cubic.getP1() +
Toshihiro Shimizu 890ddd
				 ((3 * S * T * T) - (S * T * 3 / 2)) * cubic.getP2() +
Toshihiro Shimizu 890ddd
				 ((T * T * T) - (T * T - S * T / 2)) * cubic.getP3();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double dist_sq = norm2(dp);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (splits = 0; dist_sq > error; splits++)
Toshihiro Shimizu 890ddd
		dist_sq *= 0.125 * 0.125;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (splits == 0) {
Toshihiro Shimizu 890ddd
		TPointD p0 = cubic.getP0();
Toshihiro Shimizu 890ddd
		TPointD p1 = cubic.getP1();
Toshihiro Shimizu 890ddd
		TPointD p2 = cubic.getP2();
Toshihiro Shimizu 890ddd
		TPointD p3 = cubic.getP3();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		TPointD side01 = p1 - p0;
Toshihiro Shimizu 890ddd
		TPointD side32 = p2 - p3;
Toshihiro Shimizu 890ddd
		//  se sono verificate TUTTE le condizioni dei seguenti if nidificati, allora viene
Toshihiro Shimizu 890ddd
		//  generata un'unica quadratica per approssimare cubic. Altrimenti,
Toshihiro Shimizu 890ddd
		//  se NON viene verificata ALMENO una delle condizioni dei seguenti if nidificati, allora
Toshihiro Shimizu 890ddd
		//  cubic viene splittata ulteriormente e trattata da doComputeQuadraticsFromCubic
Toshihiro Shimizu 890ddd
		double det = -side01.x * side32.y + side01.y * side32.x; //  -cross(side01, side32)
Toshihiro Shimizu 890ddd
		if (!isAlmostZero(det))									 // side01 incidente side32 (verra' calcolata l'intersezione...)
Toshihiro Shimizu 890ddd
		{
Toshihiro Shimizu 890ddd
			TPointD side03 = p3 - p0;
Toshihiro Shimizu 890ddd
			double det01 = -side03.x * side32.y + side03.y * side32.x;
Toshihiro Shimizu 890ddd
			double det32 = side01.x * side03.y - side01.y * side03.x;
Toshihiro Shimizu 890ddd
			double t01 = det01 / det;
Toshihiro Shimizu 890ddd
			double t32 = det32 / det;
Toshihiro Shimizu 890ddd
// unused variable
Toshihiro Shimizu 890ddd
#if 0 
Toshihiro Shimizu 890ddd
        TPointD p01 = p0 + t01*(p1 - p0); // debug
Toshihiro Shimizu 890ddd
        TPointD p32 = p3 + t32*(p2 - p3); // debug
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
			//TPointD intersection = p0 + t01*(p1 - p0) = p3 + t32*(p2 - p3)
Toshihiro Shimizu 890ddd
			//assert (areAlmostEqual(p0 + t01*(p1 - p0), p3 + t32*(p2 - p3)));
Toshihiro Shimizu 890ddd
			if (t01 >= 1 && t32 >= 1) { //  poligonale p0_p1_p2_p3 NON e' a "zig-zag"
Toshihiro Shimizu 890ddd
				double norm2_side0p = norm2(t01 * side01);
Toshihiro Shimizu 890ddd
				double norm2_side3p = norm2(t32 * side32);
Toshihiro Shimizu 890ddd
				if (!isAlmostZero(norm2_side0p, 1e-20) && !isAlmostZero(norm2_side3p, 1e-20)) { //  la condizione puo' essere violata anche nel caso !isAlmostZero(det) == true
Toshihiro Shimizu 890ddd
					double norm2_side03 = norm2(side03);
Toshihiro Shimizu 890ddd
					double tmp = norm2_side0p + norm2_side3p - norm2_side03;
Toshihiro Shimizu 890ddd
					//double cs = tmp/(2*sqrt(norm2_side0p)*sqrt(norm2_side3p));  //  debug
Toshihiro Shimizu 890ddd
					double cs_sign = tmp >= 0 ? 1 : -1; //  cs2 "perde" il segno (cs2 = cs*cs)
Toshihiro Shimizu 890ddd
					//  th coseno: gli assert del tipo acos(sqrt(cs2)) sono commentati perche' puo' essere cs2 > 1 per errori
Toshihiro Shimizu 890ddd
					//  di approssimazione: tuttavia la cosa non costituisce problema (acos non viene mai eseguta...)
Toshihiro Shimizu 890ddd
					double cs2 = sq(tmp) / (4 * norm2_side0p * norm2_side3p);
Toshihiro Shimizu 890ddd
					//assert (0 <= cs2 && cs2 <= 1 + TConsts::epsilon);
Toshihiro Shimizu 890ddd
					assert(areAlmostEqual(tsign(cs_sign) * sqrt(cs2), tmp / (2 * sqrt(norm2_side0p) * sqrt(norm2_side3p))));
Shinya Kitaoka ee259f
					assert(!(cs_sign < 0) || acos(-sqrt(cs2)) > 10 * M_PI_180); //  cs_sign < 0 => acos(-sqrt(cs2)) > 10°
Toshihiro Shimizu 890ddd
					if (cs_sign < 0 || cs2 < 0.969846)								   //  cos(10°)^2 = 0.969846
Toshihiro Shimizu 890ddd
					{																   //  limita distanza di intersection: elimina quadratiche "cappio" (con p1 "lontano")
Shinya Kitaoka ee259f
						//assert (acos(tsign(cs_sign)*sqrt(cs2)) > 10*M_PI_180);
Shinya Kitaoka ee259f
						assert(tsign(cs_sign) * sqrt(cs2) < cos(10 * M_PI_180));
Toshihiro Shimizu 890ddd
						TPointD intersection = p0 + t01 * (p1 - p0);																//  = p2 + t32*(p2 - p3)
Toshihiro Shimizu 890ddd
						TThickPoint p(intersection.x, intersection.y, 0.5 * (cubic.getThickP1().thick + cubic.getThickP2().thick)); //  compatibilita' precedente funzione
Toshihiro Shimizu 890ddd
						chunkArray.push_back(new TThickQuadratic(cubic.getThickP0(), p, cubic.getThickP3()));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef _DEBUG
Toshihiro Shimizu 890ddd
						TThickQuadratic *lastTq = chunkArray.back();
Toshihiro Shimizu 890ddd
						TThickPoint pDeb = lastTq->getThickP0();
Toshihiro Shimizu 890ddd
						assert(_finite(pDeb.x));
Toshihiro Shimizu 890ddd
						assert(_finite(pDeb.y));
Toshihiro Shimizu 890ddd
						assert(_finite(pDeb.thick));
Toshihiro Shimizu 890ddd
						pDeb = lastTq->getThickP1();
Toshihiro Shimizu 890ddd
						assert(_finite(pDeb.x));
Toshihiro Shimizu 890ddd
						assert(_finite(pDeb.y));
Toshihiro Shimizu 890ddd
						assert(_finite(pDeb.thick));
Toshihiro Shimizu 890ddd
						pDeb = lastTq->getThickP2();
Toshihiro Shimizu 890ddd
						assert(_finite(pDeb.x));
Toshihiro Shimizu 890ddd
						assert(_finite(pDeb.y));
Toshihiro Shimizu 890ddd
						assert(_finite(pDeb.thick));
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
						numSaved++; //  variabile debug: compatibilita' precedente funzione
Toshihiro Shimizu 890ddd
						return;
Toshihiro Shimizu 890ddd
					}
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		} else {
Toshihiro Shimizu 890ddd
			TPointD side03 = p3 - p0;
Toshihiro Shimizu 890ddd
			double det01 = -side03.x * side32.y + side03.y * side32.x;
Toshihiro Shimizu 890ddd
			if (isAlmostZero(det01)) {
Toshihiro Shimizu 890ddd
				//e' una retta!, crea unica quadratica con p in mezzo a p1 e p2
Toshihiro Shimizu 890ddd
				chunkArray.push_back(new TThickQuadratic(
Toshihiro Shimizu 890ddd
					cubic.getThickP0(),
Toshihiro Shimizu 890ddd
					(cubic.getThickP1() + cubic.getThickP2()) * 0.5,
Toshihiro Shimizu 890ddd
					cubic.getThickP3()));
Toshihiro Shimizu 890ddd
				numSaved++; //  variabile debug: compatibilita' precedente funzione
Toshihiro Shimizu 890ddd
				return;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		//else: se arriva qui, almeno una delle condizioni negli if nidificati precedenti e' falsa
Toshihiro Shimizu 890ddd
		splits++;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	doComputeQuadraticsFromCubic(cubic, splits - 1, chunkArray);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
//  TStroke *computeQuadStroke(const TCubicStroke& cubic, double error)
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//! Ricava uno stroke quadratico da uno stroke cubico
Toshihiro Shimizu 890ddd
TStroke *computeQuadStroke(const TCubicStroke &cubic)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	vector<tthickquadratic *=""> chunkArray;</tthickquadratic>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (UINT i = 0; i < cubic.m_cubicChunkArray->size(); i++) {
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		TThickCubic tmp(*(*cubic.m_cubicChunkArray)[i]);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef _DEBUG
Toshihiro Shimizu 890ddd
		{
Toshihiro Shimizu 890ddd
			TThickPoint p = tmp.getThickP0();
Toshihiro Shimizu 890ddd
			assert(_finite(p.x));
Toshihiro Shimizu 890ddd
			assert(_finite(p.y));
Toshihiro Shimizu 890ddd
			assert(_finite(p.thick));
Toshihiro Shimizu 890ddd
			p = tmp.getThickP1();
Toshihiro Shimizu 890ddd
			assert(_finite(p.x));
Toshihiro Shimizu 890ddd
			assert(_finite(p.y));
Toshihiro Shimizu 890ddd
			assert(_finite(p.thick));
Toshihiro Shimizu 890ddd
			p = tmp.getThickP2();
Toshihiro Shimizu 890ddd
			assert(_finite(p.x));
Toshihiro Shimizu 890ddd
			assert(_finite(p.y));
Toshihiro Shimizu 890ddd
			assert(_finite(p.thick));
Toshihiro Shimizu 890ddd
			p = tmp.getThickP3();
Toshihiro Shimizu 890ddd
			assert(_finite(p.x));
Toshihiro Shimizu 890ddd
			assert(_finite(p.y));
Toshihiro Shimizu 890ddd
			assert(_finite(p.thick));
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// this code use a Chebychev version of degree reduction
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// This code is for old algorithm only:
Toshihiro Shimizu 890ddd
		computeQuadraticsFromCubic(tmp, 2.0 /*0.5*/, chunkArray);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TStroke *outStroke = TStroke::create(chunkArray);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	clearPointerContainer(chunkArray);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return outStroke;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
} // namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// helper function (defined in tstroke.h)
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void computeQuadraticsFromCubic(const TThickPoint &p0,
Toshihiro Shimizu 890ddd
								const TThickPoint &p1,
Toshihiro Shimizu 890ddd
								const TThickPoint &p2,
Toshihiro Shimizu 890ddd
								const TThickPoint &p3,
Toshihiro Shimizu 890ddd
								double error,
Toshihiro Shimizu 890ddd
								vector<tthickquadratic *=""> &chunkArray)</tthickquadratic>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	computeQuadraticsFromCubic(TThickCubic(p0, p1, p2, p3), error, chunkArray);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TCubicStroke::TCubicStroke()
Toshihiro Shimizu 890ddd
	: m_bBox()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_cubicChunkArray = new TThickCubicArray();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TCubicStroke::TCubicStroke(const TCubicStroke &stroke)
Toshihiro Shimizu 890ddd
	: m_bBox(stroke.m_bBox), m_cubicChunkArray(stroke.m_cubicChunkArray)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_cubicChunkArray = new TThickCubicArray(*stroke.m_cubicChunkArray);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TCubicStroke::~TCubicStroke()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (m_cubicChunkArray) {
Toshihiro Shimizu 890ddd
		while (!m_cubicChunkArray->empty()) {
Toshihiro Shimizu 890ddd
			delete m_cubicChunkArray->back();
Toshihiro Shimizu 890ddd
			m_cubicChunkArray->pop_back();
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		delete m_cubicChunkArray;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TCubicStroke::TCubicStroke(const vector<t3dpointd> &pointsArray3D,</t3dpointd>
Toshihiro Shimizu 890ddd
						   double error, bool doDetectCorners)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	vector<int> corners;</int>
Toshihiro Shimizu 890ddd
	corners.push_back(0);
Toshihiro Shimizu 890ddd
	if (doDetectCorners)
Toshihiro Shimizu 890ddd
		detectCorners(pointsArray3D, 3, 3, 15, 100, corners);
Toshihiro Shimizu 890ddd
	corners.push_back(pointsArray3D.size() - 1);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifndef USE_NEW_3D_ERROR_COMPUTE
Toshihiro Shimizu 890ddd
	error *= error;
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_cubicChunkArray = new vector<tthickcubic *="">();</tthickcubic>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (int i = 1; i < (int)corners.size(); i++) {
Toshihiro Shimizu 890ddd
		int size = corners[i] - corners[i - 1] + 1;
Toshihiro Shimizu 890ddd
		int firstPoint = corners[i - 1];
Toshihiro Shimizu 890ddd
		T3DPointD
Toshihiro Shimizu 890ddd
			tanLeft,
Toshihiro Shimizu 890ddd
			tanRigth;
Toshihiro Shimizu 890ddd
		assert(size > 0);
Toshihiro Shimizu 890ddd
		if (size > 1) //  capita che corners[i] = corners[i - 1] ("clic" senza drag oppure bug (noto!!!) del cornerDetector)
Toshihiro Shimizu 890ddd
		{
Toshihiro Shimizu 890ddd
			tanLeft = -pointsArray3D[firstPoint + 1] + pointsArray3D[firstPoint];
Toshihiro Shimizu 890ddd
			tanRigth = pointsArray3D[firstPoint + size - 2] - pointsArray3D[firstPoint + size - 1];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			if (norm2(tanLeft) > 0)
Toshihiro Shimizu 890ddd
				tanLeft = normalize(tanLeft);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			if (norm2(tanRigth) > 0)
Toshihiro Shimizu 890ddd
				tanRigth = normalize(tanRigth);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			fitCubic3D(
Toshihiro Shimizu 890ddd
				&pointsArray3D[firstPoint],
Toshihiro Shimizu 890ddd
				size,
Toshihiro Shimizu 890ddd
				tanLeft,
Toshihiro Shimizu 890ddd
				tanRigth,
Toshihiro Shimizu 890ddd
				error);
Toshihiro Shimizu 890ddd
		} else if (pointsArray3D.size() == 1) {
Toshihiro Shimizu 890ddd
			//  caso in cui i non calcola nessun corner a meno di quello iniziale
Toshihiro Shimizu 890ddd
			//  e finale coincidenti: 1 solo punto campionato ("clic" senza drag)
Toshihiro Shimizu 890ddd
			assert(size == 1);
Toshihiro Shimizu 890ddd
			assert(corners.size() == 2);
Toshihiro Shimizu 890ddd
			assert(corners[0] == 0);
Toshihiro Shimizu 890ddd
			assert(corners[1] == 0);
Toshihiro Shimizu 890ddd
			m_cubicChunkArray->push_back(new TThickCubic(pointsArray3D[0],
Toshihiro Shimizu 890ddd
														 pointsArray3D[0],
Toshihiro Shimizu 890ddd
														 pointsArray3D[0],
Toshihiro Shimizu 890ddd
														 pointsArray3D[0]));
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TCubicStroke::fitCubic3D(const T3DPointD pointsArrayBegin[],
Toshihiro Shimizu 890ddd
							  int size,
Toshihiro Shimizu 890ddd
							  const T3DPointD &tangentLeft,
Toshihiro Shimizu 890ddd
							  const T3DPointD &tangentRight,
Toshihiro Shimizu 890ddd
							  double error)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int maxIterations = 4;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (size == 2) {
Toshihiro Shimizu 890ddd
		double dist = tdistance(*pointsArrayBegin, *(pointsArrayBegin + 1)) / 3.0;
Toshihiro Shimizu 890ddd
		TThickCubic *strokeCubicChunk = new TThickCubic(*pointsArrayBegin,
Toshihiro Shimizu 890ddd
														*pointsArrayBegin - dist * tangentLeft,
Toshihiro Shimizu 890ddd
														*(pointsArrayBegin + 1) + dist * tangentRight,
Toshihiro Shimizu 890ddd
														*(pointsArrayBegin + 1));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		m_cubicChunkArray->push_back(strokeCubicChunk);
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double *u = chordLengthParameterize3D(pointsArrayBegin, size);
Toshihiro Shimizu 890ddd
	TThickCubic *cubic = generateCubic3D(pointsArrayBegin, u, size, tangentLeft, tangentRight);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int splitPoint;
Toshihiro Shimizu 890ddd
	double maxError = computeMaxError3D(*cubic, pointsArrayBegin, size, u, splitPoint);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (maxError < error) {
Toshihiro Shimizu 890ddd
		delete[] u;
Toshihiro Shimizu 890ddd
		m_cubicChunkArray->push_back(cubic);
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//if (maxError
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		double *uPrime = 0;
Toshihiro Shimizu 890ddd
		for (int i = 0; i < maxIterations; i++) {
Toshihiro Shimizu 890ddd
			//delete uPrime;
Toshihiro Shimizu 890ddd
			uPrime = reparameterize3D(*cubic, pointsArrayBegin, size, u);
Toshihiro Shimizu 890ddd
			if (!uPrime)
Toshihiro Shimizu 890ddd
				break;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			delete cubic;
Toshihiro Shimizu 890ddd
			cubic = generateCubic3D(pointsArrayBegin, uPrime, size, tangentLeft, tangentRight);
Toshihiro Shimizu 890ddd
			maxError = computeMaxError3D(*cubic, pointsArrayBegin, size, uPrime, splitPoint);
Toshihiro Shimizu 890ddd
			if (maxError < error) {
Toshihiro Shimizu 890ddd
				delete uPrime;
Toshihiro Shimizu 890ddd
				delete[] u;
Toshihiro Shimizu 890ddd
				m_cubicChunkArray->push_back(cubic);
Toshihiro Shimizu 890ddd
				return;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
			delete[] u;
Toshihiro Shimizu 890ddd
			u = uPrime;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	delete[] u;
Toshihiro Shimizu 890ddd
	delete cubic;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	T3DPointD centralTangent;
Toshihiro Shimizu 890ddd
	if (*(pointsArrayBegin + splitPoint - 1) == *(pointsArrayBegin + splitPoint + 1))
Toshihiro Shimizu 890ddd
		centralTangent = normalize(*(pointsArrayBegin + splitPoint) - *(pointsArrayBegin + splitPoint + 1));
Toshihiro Shimizu 890ddd
	else
Toshihiro Shimizu 890ddd
		centralTangent = normalize(*(pointsArrayBegin + splitPoint - 1) - *(pointsArrayBegin + splitPoint + 1));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	fitCubic3D(pointsArrayBegin, splitPoint + 1, tangentLeft, centralTangent, error);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	fitCubic3D(pointsArrayBegin + splitPoint, size - splitPoint, centralTangent, tangentRight, error);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TThickCubic *TCubicStroke::generateCubic3D(const T3DPointD pointsArrayBegin[],
Toshihiro Shimizu 890ddd
										   const double uPrime[],
Toshihiro Shimizu 890ddd
										   int size,
Toshihiro Shimizu 890ddd
										   const T3DPointD &tangentLeft,
Toshihiro Shimizu 890ddd
										   const T3DPointD &tangentRight)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	double X[2], C[2][2];
Toshihiro Shimizu 890ddd
	int i;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	T3DPointD p0 = *pointsArrayBegin;
Toshihiro Shimizu 890ddd
	T3DPointD p3 = *(pointsArrayBegin + size - 1);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	C[0][0] = C[0][1] = X[0] = 0;
Toshihiro Shimizu 890ddd
	C[1][0] = C[1][1] = X[1] = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (i = 0; i < size; i++) {
Campbell Barton 5db682
		const T3DPointD A[2] = {
Campbell Barton 5db682
			tangentLeft  * B1(uPrime[i]),
Campbell Barton 5db682
			tangentRight * B2(uPrime[i]),
Campbell Barton 5db682
		};
Campbell Barton 5db682
Campbell Barton 5db682
		C[0][0] += A[0] * A[0];
Campbell Barton 5db682
		C[0][1] += A[0] * A[1];
Campbell Barton 5db682
		C[1][1] += A[1] * A[1];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		C[1][0] = C[0][1];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		T3DPointD tmp = *(pointsArrayBegin + i) - (B0plusB1(uPrime[i]) * p0) +
Toshihiro Shimizu 890ddd
						B2plusB3(uPrime[i]) * p3;
Campbell Barton 5db682
		X[0] += A[0] * tmp;
Campbell Barton 5db682
		X[1] += A[1] * tmp;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double detC0C1 = C[0][0] * C[1][1] - C[0][1] * C[1][0];
Toshihiro Shimizu 890ddd
	double detC0X = X[1] * C[0][0] - X[0] * C[0][1];
Toshihiro Shimizu 890ddd
	double detXC1 = X[0] * C[1][1] - X[1] * C[0][1];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (isAlmostZero(detC0C1))
Toshihiro Shimizu 890ddd
		detC0C1 = C[0][0] * C[1][1] * 10e-12;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double alphaL = detXC1 / detC0C1;
Toshihiro Shimizu 890ddd
	double alphaR = detC0X / detC0C1;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	/////////////////////////////////////////////////////////////////////////////////////////////////
Toshihiro Shimizu 890ddd
	//
Toshihiro Shimizu 890ddd
	//  il problema e' che i valori stupidi per alpha non adrebbere messi solo quando ci si accorge
Toshihiro Shimizu 890ddd
	//  che il segno e' sbagliato, ma anche se i valori sono troppo alti. Ma come fare a valutarlo?
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//  Intanto bisognerebbe accertarsi che 'sti valori alcune volte sono cosi' assurdi solo per problemi
Toshihiro Shimizu 890ddd
	//  di approssimazione e non per bachi nel codice
Toshihiro Shimizu 890ddd
	//
Toshihiro Shimizu 890ddd
	/////////////////////////////////////////////////////////////////////////////////////////////////
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double xmin = (numeric_limits<double>::max)();</double>
Toshihiro Shimizu 890ddd
	double ymin = (numeric_limits<double>::max)();</double>
Toshihiro Shimizu 890ddd
	double xmax = -(numeric_limits<double>::max)();</double>
Toshihiro Shimizu 890ddd
	double ymax = -(numeric_limits<double>::max)();</double>
Toshihiro Shimizu 890ddd
	double thickmin = (numeric_limits<double>::max)();</double>
Toshihiro Shimizu 890ddd
	double thickmax = -(numeric_limits<double>::max)();</double>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (i = 0; i < size; i++) {
Toshihiro Shimizu 890ddd
		if (pointsArrayBegin[i].x < xmin)
Toshihiro Shimizu 890ddd
			xmin = pointsArrayBegin[i].x;
Toshihiro Shimizu 890ddd
		if (pointsArrayBegin[i].x > xmax)
Toshihiro Shimizu 890ddd
			xmax = pointsArrayBegin[i].x;
Toshihiro Shimizu 890ddd
		if (pointsArrayBegin[i].y < ymin)
Toshihiro Shimizu 890ddd
			ymin = pointsArrayBegin[i].y;
Toshihiro Shimizu 890ddd
		if (pointsArrayBegin[i].y > ymax)
Toshihiro Shimizu 890ddd
			ymax = pointsArrayBegin[i].y;
Toshihiro Shimizu 890ddd
		if (pointsArrayBegin[i].z < thickmin)
Toshihiro Shimizu 890ddd
			thickmin = pointsArrayBegin[i].z;
Toshihiro Shimizu 890ddd
		if (pointsArrayBegin[i].z > thickmax)
Toshihiro Shimizu 890ddd
			thickmax = pointsArrayBegin[i].z;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double lx = xmax - xmin;
Toshihiro Shimizu 890ddd
	assert(lx >= 0);
Toshihiro Shimizu 890ddd
	double ly = ymax - ymin;
Toshihiro Shimizu 890ddd
	assert(ly >= 0);
Toshihiro Shimizu 890ddd
	double lt = thickmax - thickmin;
Toshihiro Shimizu 890ddd
	assert(lt >= 0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	xmin -= lx;
Toshihiro Shimizu 890ddd
	xmax += lx;
Toshihiro Shimizu 890ddd
	ymin -= ly;
Toshihiro Shimizu 890ddd
	ymax += ly;
Toshihiro Shimizu 890ddd
	thickmin -= lt;
Toshihiro Shimizu 890ddd
	thickmax += lt;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TRectD bbox(xmin, ymin, xmax, ymax);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (alphaL < 0.0 || alphaR < 0.0)
Toshihiro Shimizu 890ddd
		alphaL = alphaR = sqrt(tdistance2(p0, p3)) / 3.0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	T3DPointD p1 = p0 - tangentLeft * alphaL;
Toshihiro Shimizu 890ddd
	T3DPointD p2 = p3 + tangentRight * alphaR;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!bbox.contains(TPointD(p1.x, p1.y)) ||
Toshihiro Shimizu 890ddd
		!bbox.contains(TPointD(p2.x, p2.y))) {
Toshihiro Shimizu 890ddd
		alphaL = alphaR = sqrt(tdistance2(p0, p3)) / 3.0;
Toshihiro Shimizu 890ddd
		p1 = p0 - tangentLeft * alphaL;
Toshihiro Shimizu 890ddd
		p2 = p3 + tangentRight * alphaR;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (p1.z < thickmin)
Toshihiro Shimizu 890ddd
		p1.z = thickmin;
Toshihiro Shimizu 890ddd
	else if (p1.z > thickmax)
Toshihiro Shimizu 890ddd
		p1.z = thickmax;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (p2.z < thickmin)
Toshihiro Shimizu 890ddd
		p2.z = thickmin;
Toshihiro Shimizu 890ddd
	else if (p2.z > thickmax)
Toshihiro Shimizu 890ddd
		p2.z = thickmax;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TThickCubic *thickCubic = new TThickCubic(TThickPoint(p0.x, p0.y, p0.z),
Toshihiro Shimizu 890ddd
											  TThickPoint(p1.x, p1.y, p1.z),
Toshihiro Shimizu 890ddd
											  TThickPoint(p2.x, p2.y, p2.z),
Toshihiro Shimizu 890ddd
											  TThickPoint(p3.x, p3.y, p3.z));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return thickCubic;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
//! Restituisce uno stroke da un vettore di TThickPoint
Toshihiro Shimizu 890ddd
/*!
Toshihiro Shimizu 890ddd
  Trasforma un vettore di TThickPoint in un vettore di T3DPointD che usa per trovare un
Toshihiro Shimizu 890ddd
	TCubicStroke, cioe' uno stroke cubico. Da questo trova lo stroke quadratico.
Toshihiro Shimizu 890ddd
  */
Toshihiro Shimizu 890ddd
TStroke *TStroke::interpolate(const vector<tthickpoint> &points, double error, bool findCorners)</tthickpoint>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	vector<t3dpointd> pointsArray3D;</t3dpointd>
Toshihiro Shimizu 890ddd
	convert(points, pointsArray3D);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TCubicStroke cubicStroke(pointsArray3D, error, findCorners);
Toshihiro Shimizu 890ddd
	numSaved = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//  TStroke *stroke = computeQuadStroke(cubicStroke,error);
Toshihiro Shimizu 890ddd
	TStroke *stroke = computeQuadStroke(cubicStroke);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef _DEBUG
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	UINT cpIndex = 0;
Toshihiro Shimizu 890ddd
	TThickPoint p;
Toshihiro Shimizu 890ddd
	for (; cpIndex != (UINT)stroke->getControlPointCount(); cpIndex++) {
Toshihiro Shimizu 890ddd
		p = stroke->getControlPoint(cpIndex);
Toshihiro Shimizu 890ddd
		assert(_finite(p.x));
Toshihiro Shimizu 890ddd
		assert(_finite(p.y));
Toshihiro Shimizu 890ddd
		assert(_finite(p.thick));
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	removeNullQuadratic(stroke);
Toshihiro Shimizu 890ddd
	stroke->invalidate();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return stroke;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
//! Restituisce uno stroke da un vettore di TThickQuadratic
Toshihiro Shimizu 890ddd
/*!
Toshihiro Shimizu 890ddd
  Estrae dalle curve i punti di controllo e crea con questi un nuovo stroke
Toshihiro Shimizu 890ddd
  */
Toshihiro Shimizu 890ddd
TStroke *TStroke::create(const vector<tthickquadratic *=""> &curves)</tthickquadratic>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (curves.empty())
Toshihiro Shimizu 890ddd
		return 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// make a vector of control points
Toshihiro Shimizu 890ddd
	vector<tthickpoint> ctrlPnts;</tthickpoint>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	extractStrokeControlPoints(curves, ctrlPnts);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TStroke *stroke = new TStroke(ctrlPnts);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	stroke->invalidate();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return stroke;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//============================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TStrokeProp::TStrokeProp(const TStroke *stroke)
Toshihiro Shimizu 890ddd
	: m_stroke(stroke), m_strokeChanged(true), m_mutex()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//============================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TStroke::OutlineOptions::OutlineOptions()
Toshihiro Shimizu 890ddd
	: m_capStyle(ROUND_CAP), m_joinStyle(ROUND_JOIN), m_miterLower(0.0), m_miterUpper(4.0)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TStroke::OutlineOptions::OutlineOptions(
Toshihiro Shimizu 890ddd
	UCHAR capStyle, UCHAR joinStyle, double lower, double upper)
Toshihiro Shimizu 890ddd
	: m_capStyle(capStyle), m_joinStyle(joinStyle), m_miterLower(lower), m_miterUpper(upper)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
}