Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// outlineApproximation.cpp: implementation of the outlineApproximation class.
Toshihiro Shimizu 890ddd
//
Toshihiro Shimizu 890ddd
//////////////////////////////////////////////////////////////////////
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "tstrokeoutline.h"
Toshihiro Shimizu 890ddd
#include "tstroke.h"
Toshihiro Shimizu 890ddd
#include "tcurves.h"
Toshihiro Shimizu 890ddd
#include "tmathutil.h"
Toshihiro Shimizu 890ddd
#include "tgl.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//#include "tcolorfunctions.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
typedef std::pair<tquadratic *="" *,="" tquadratic=""> outlineEdge;</tquadratic>
Toshihiro Shimizu 890ddd
typedef std::vector<outlineedge> outlineBoundary;</outlineedge>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
const double infDouble = (std::numeric_limits<double>::max)();</double>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*
Toshihiro Shimizu 890ddd
ONLY FOT TEST
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TSegment  g_tangEnvelope_1;  
Toshihiro Shimizu 890ddd
TSegment  g_tangEnvelope_2;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
vector<tquadratic>  g_testOutline;</tquadratic>
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
namespace Outline
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class infinityCurvature
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class notValidOutline
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
/*
Toshihiro Shimizu 890ddd
  This formule is derived from Graphic Gems pag. 600
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
    e = h^2 |a|/8
Toshihiro Shimizu 890ddd
  
Toshihiro Shimizu 890ddd
      e = pixel size
Toshihiro Shimizu 890ddd
      h = step
Toshihiro Shimizu 890ddd
      a = acceleration of curve (for a quadratic is a costant value)
Toshihiro Shimizu 890ddd
  */
Toshihiro Shimizu 890ddd
double localComputeStep(const TQuadratic &quad, double pixelSize)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	double step = 2;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TPointD A = quad.getP0() - 2.0 * quad.getP1() + quad.getP2(); // 2*A is the acceleration of the curve
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double A_len = norm(A);
Toshihiro Shimizu 890ddd
	if (A_len > 0)
Toshihiro Shimizu 890ddd
		step = TConsts::sqrt2 * sqrt(pixelSize / A_len);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return step;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// selezionano lo spicchio da calcolare nella costruzione dei tappi
Toshihiro Shimizu 890ddd
// (semicirconferenze iniziali e finali)
Toshihiro Shimizu 890ddd
const int QUARTER_BEGIN = 1;
Toshihiro Shimizu 890ddd
const int QUARTER_END = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// selezionano il pezzo d'outline da calcolare (sopra/sotto)
Toshihiro Shimizu 890ddd
const int OUTLINE_UP = 1;
Toshihiro Shimizu 890ddd
const int OUTLINE_DOWN = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// utili
Toshihiro Shimizu 890ddd
const double ratio_1_3 = 1.0 / 3.0;
Toshihiro Shimizu 890ddd
const double ratio_2_3 = 2.0 / 3.0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// torna la curvature per t=0
Toshihiro Shimizu 890ddd
template <class t=""></class>
Toshihiro Shimizu 890ddd
double curvature_t0(const T *curve)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	assert(curve);
Toshihiro Shimizu 890ddd
	TPointD v1 = curve->getP1() - curve->getP0();
Toshihiro Shimizu 890ddd
	TPointD v2 = curve->getP2() - curve->getP1();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double v_cross = cross(v1, v2);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (isAlmostZero(v_cross))
Toshihiro Shimizu 890ddd
		return infDouble;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return ratio_2_3 * v_cross / pow(norm(v1), ratio_1_3);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// torna la curvature per t=1
Toshihiro Shimizu 890ddd
double curvature_t1(const TThickQuadratic *curve)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	assert(curve);
Toshihiro Shimizu 890ddd
	TThickQuadratic tmp;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	tmp.setThickP0(curve->getThickP2());
Toshihiro Shimizu 890ddd
	tmp.setThickP1(curve->getThickP1());
Toshihiro Shimizu 890ddd
	tmp.setThickP2(curve->getThickP0());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return curvature_t0(&tmp);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// estrae il punto dell'outline per il parametro specificato
Toshihiro Shimizu 890ddd
// N.B: e' sbagliata non tiene conto degli inviluppi
Toshihiro Shimizu 890ddd
TPointD getPointInOutline(const TThickQuadratic *tq, double t, int upOrDown)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	assert(tq);
Toshihiro Shimizu 890ddd
	const TThickPoint &p = tq->getThickPoint(t);
Toshihiro Shimizu 890ddd
	TPointD n = tq->getSpeed(t);
Toshihiro Shimizu 890ddd
	if (norm2(n)) {
Toshihiro Shimizu 890ddd
		n = normalize(n);
Toshihiro Shimizu 890ddd
		n = upOrDown ? rotate90(n) : rotate270(n);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return convert(p) + p.thick * n;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool checkPointInOutline(const TPointD &pointToTest,
Toshihiro Shimizu 890ddd
						 const TThickQuadratic *tq,
Toshihiro Shimizu 890ddd
						 double t,
Toshihiro Shimizu 890ddd
						 double error)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	assert(tq);
Toshihiro Shimizu 890ddd
	TThickPoint tpnt = tq->getThickPoint(t);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (fabs(sq(pointToTest.x - tpnt.x) +
Toshihiro Shimizu 890ddd
			 sq(pointToTest.y - tpnt.y) -
Toshihiro Shimizu 890ddd
			 sq(tpnt.thick)) < error)
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
// costruisce un ramo di outline (sopra o sotto) per una quadratica cicciona
Toshihiro Shimizu 890ddd
TQuadratic *makeOutlineForThickQuadratic(const TThickQuadratic *tq, int upOrDown)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	assert(tq);
Toshihiro Shimizu 890ddd
	// if(!outline) return 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TThickPoint
Toshihiro Shimizu 890ddd
		p0 = tq->getThickP0(),
Toshihiro Shimizu 890ddd
		//p1 = tq->getThickP0(),
Toshihiro Shimizu 890ddd
		p2 = tq->getThickP2();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TPointD t0 = tq->getP1() - tq->getP0();
Toshihiro Shimizu 890ddd
	TPointD t1 = tq->getP2() - tq->getP1();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (t0 == t1)
Toshihiro Shimizu 890ddd
		return 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TPointD
Toshihiro Shimizu 890ddd
		N0 = tq->getSpeed(0.0),
Toshihiro Shimizu 890ddd
		N2 = tq->getSpeed(1.0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!norm2(N0) && !norm2(N2))
Toshihiro Shimizu 890ddd
		throw Outline::notValidOutline();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (norm2(N0)) {
Toshihiro Shimizu 890ddd
		N0 = normalize(N0);
Toshihiro Shimizu 890ddd
		N0 = upOrDown ? rotate90(N0) : rotate270(N0);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (norm2(N2)) {
Toshihiro Shimizu 890ddd
		N2 = normalize(N2);
Toshihiro Shimizu 890ddd
		N2 = upOrDown ? rotate90(N2) : rotate270(N2);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TPointD p0aux = (convert(p0) + p0.thick * N0);
Toshihiro Shimizu 890ddd
	TPointD p2aux = (convert(p2) + p2.thick * N2);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TQuadratic
Toshihiro Shimizu 890ddd
		radius(TPointD(tq->getThickP0().thick, 0.0),
Toshihiro Shimizu 890ddd
			   TPointD(tq->getThickP1().thick, 0.0),
Toshihiro Shimizu 890ddd
			   TPointD(tq->getThickP2().thick, 0.0));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TPointD r0 = radius.getSpeed(0.0);
Toshihiro Shimizu 890ddd
	TPointD r1 = radius.getSpeed(1.0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TPointD
Toshihiro Shimizu 890ddd
		v0,
Toshihiro Shimizu 890ddd
		v2;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double ct0 = curvature_t0(tq);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (ct0 != infDouble)
Toshihiro Shimizu 890ddd
		v0 = (1 + p0.thick * ct0) * t0 + 0.5 * r0.x * N0;
Toshihiro Shimizu 890ddd
	else
Toshihiro Shimizu 890ddd
		v0 = r0.x * N0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double ct1 = curvature_t1(tq);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (ct1 != infDouble)
Toshihiro Shimizu 890ddd
		v2 = (1 + p2.thick * ct1) * t1 + 0.5 * r1.x * N2;
Toshihiro Shimizu 890ddd
	else
Toshihiro Shimizu 890ddd
		v2 = r1.x * N2;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	/*
Toshihiro Shimizu 890ddd
    try {
Toshihiro Shimizu 890ddd
      v0 = (1 + p0.thick * curvature_t0( tq )) * t0 + 0.5 * r0.x * N0;
Toshihiro Shimizu 890ddd
    }
Toshihiro Shimizu 890ddd
    catch( Outline::infinityCurvature& ) {
Toshihiro Shimizu 890ddd
    }
Toshihiro Shimizu 890ddd
    
Toshihiro Shimizu 890ddd
    try {
Toshihiro Shimizu 890ddd
      v2 = (1 + p2.thick * curvature_t1( tq )) * t1 + 0.5 * r1.x * N2;
Toshihiro Shimizu 890ddd
    }
Toshihiro Shimizu 890ddd
    catch( Outline::infinityCurvature& ) {
Toshihiro Shimizu 890ddd
    }
Toshihiro Shimizu 890ddd
    */
Toshihiro Shimizu 890ddd
	//    g_tangEnvelope_1.setP0( outline.getP0() );
Toshihiro Shimizu 890ddd
	//    g_tangEnvelope_1.setP1( outline.getP0() + v0 );
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//    g_tangEnvelope_2.setP0( outline.getP2() );
Toshihiro Shimizu 890ddd
	//    g_tangEnvelope_2.setP1( outline.getP2() + v2 );
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//  solve sistem  p1 = p0 + k * v1 = p2 + m * v2 to find
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double det = v0.x * v0.y - v2.x * v2.y;
Toshihiro Shimizu 890ddd
	if (areAlmostEqual(det, 0.0))
Toshihiro Shimizu 890ddd
		return 0;
Toshihiro Shimizu 890ddd
	double xsol;
Toshihiro Shimizu 890ddd
	try {
Toshihiro Shimizu 890ddd
		xsol = ((p0aux.x - p2aux.x) * v2.y - (p0aux.y - p2aux.y) * v2.x) / det;
Toshihiro Shimizu 890ddd
		//tsolveSistem( A, 2, b );
Toshihiro Shimizu 890ddd
	} catch (TMathException &) {
Toshihiro Shimizu 890ddd
		return new TQuadratic((upOrDown) ? p0aux : p2aux, (p0aux + p2aux) * 0.5, (upOrDown) ? p2aux : p0aux);
Toshihiro Shimizu 890ddd
	} catch (std::exception &e) {
Shinya Kitaoka 3bfa54
		std::string s(e.what());
Toshihiro Shimizu 890ddd
		abort();
Toshihiro Shimizu 890ddd
	} catch (...) {
Toshihiro Shimizu 890ddd
		abort();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return new TQuadratic((upOrDown) ? p0aux : p2aux, p0aux + xsol * v0, (upOrDown) ? p2aux : p0aux);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*
Toshihiro Shimizu 890ddd
    costruisce l'outline per una singola quadratica senza 
Toshihiro Shimizu 890ddd
    inserire le semicirconferenze iniziali e finali
Toshihiro Shimizu 890ddd
   */
Toshihiro Shimizu 890ddd
void makeOutline(/*std::ofstream& cout,*/
Toshihiro Shimizu 890ddd
				 outlineBoundary &outl,
Toshihiro Shimizu 890ddd
				 const TThickQuadratic &t,
Toshihiro Shimizu 890ddd
				 double error)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	outlineEdge edge;
Toshihiro Shimizu 890ddd
	const TThickQuadratic *tq = &t;
Toshihiro Shimizu 890ddd
	edge.first = edge.second = 0;
Toshihiro Shimizu 890ddd
	try {
Toshihiro Shimizu 890ddd
		edge.first = makeOutlineForThickQuadratic(tq, OUTLINE_UP);
Toshihiro Shimizu 890ddd
		edge.second = makeOutlineForThickQuadratic(tq, OUTLINE_DOWN);
Toshihiro Shimizu 890ddd
	} catch (Outline::notValidOutline &) {
Toshihiro Shimizu 890ddd
		delete edge.first;
Toshihiro Shimizu 890ddd
		delete edge.second;
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	const TQuadratic *q_up = edge.first;
Toshihiro Shimizu 890ddd
	const TQuadratic *q_down = edge.second;
Toshihiro Shimizu 890ddd
	const double parameterTest = 0.5;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// forza l'uscita per valori troppo piccoli
Toshihiro Shimizu 890ddd
	bool isAlmostAPoint =
Toshihiro Shimizu 890ddd
		areAlmostEqual(tq->getThickP0(), tq->getThickP1(), 1e-2) &&
Toshihiro Shimizu 890ddd
		areAlmostEqual(tq->getThickP1(), tq->getThickP2(), 1e-2) /*&&
Toshihiro Shimizu 890ddd
      areAlmostEqual( tq.getThickP0(), tq.getThickP2(), 1e-2 )*/;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (isAlmostAPoint ||
Toshihiro Shimizu 890ddd
		q_up && checkPointInOutline(q_up->getPoint(parameterTest), tq, parameterTest, error) &&
Toshihiro Shimizu 890ddd
			q_down && checkPointInOutline(q_down->getPoint(parameterTest), tq, parameterTest, error)) {
Toshihiro Shimizu 890ddd
		/*	if (edge.first)
Toshihiro Shimizu 890ddd
		  cout << "left: "<< *(edge.first);
Toshihiro Shimizu 890ddd
	 else
Toshihiro Shimizu 890ddd
		  cout << "left: "<< 0;
Toshihiro Shimizu 890ddd
		if (edge.second)
Toshihiro Shimizu 890ddd
		  cout << "right: "<<*(edge.second);
Toshihiro Shimizu 890ddd
	 else
Toshihiro Shimizu 890ddd
		  cout << "right: "<< 0;
Toshihiro Shimizu 890ddd
		
Toshihiro Shimizu 890ddd
		cout<
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		outl.push_back(edge);
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	} else {
Toshihiro Shimizu 890ddd
		delete edge.first;
Toshihiro Shimizu 890ddd
		delete edge.second;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TThickQuadratic
Toshihiro Shimizu 890ddd
		tq_left,
Toshihiro Shimizu 890ddd
		tq_rigth;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	tq->split(0.5, tq_left, tq_rigth);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	makeOutline(/*out,*/ outl, tq_left, error);
Toshihiro Shimizu 890ddd
	makeOutline(/*cout,*/ outl, tq_rigth, error);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void splitCircularArcIntoQuadraticCurves(const TPointD &Center,
Toshihiro Shimizu 890ddd
										 const TPointD &Pstart,
Toshihiro Shimizu 890ddd
										 const TPointD &Pend,
Shinya Kitaoka 3bfa54
										 std::vector<tquadratic *=""> &quadArray)</tquadratic>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	// It splits a circular anticlockwise arc into a sequence of quadratic bezier curves
Toshihiro Shimizu 890ddd
	// Every quadratic curve can approximate an arc no TLonger than 45 degrees (or 60).
Toshihiro Shimizu 890ddd
	// It supposes that Pstart and Pend are onto the circumference (so that their lengths
Toshihiro Shimizu 890ddd
	// are equal to tha radius of the circumference), otherwise the resulting curves could
Toshihiro Shimizu 890ddd
	// be unpredictable.
Toshihiro Shimizu 890ddd
	// The last component in quadCurve[] is an ending void curve
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	/* ---------------------------------------------------------------------------------- */
Toshihiro Shimizu 890ddd
	// If you want to split the arc into arcs no TLonger than 45 degrees (so that the whole
Toshihiro Shimizu 890ddd
	// curve will be splitted into 8 pieces) you have to set these constants as follows:
Toshihiro Shimizu 890ddd
	// cos_ang     ==> cos_45   = 0.5 * sqrt(2);
Toshihiro Shimizu 890ddd
	// sin_ang     ==> sin_45   = 0.5 * sqrt(2);
Toshihiro Shimizu 890ddd
	// tan_semiang ==> tan_22p5 = 0.4142135623730950488016887242097;
Toshihiro Shimizu 890ddd
	// N_QUAD                   = 8;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// If you want to split the arc into arcs no TLonger than 60 degrees (so that the whole
Toshihiro Shimizu 890ddd
	// curve will be splitted into 6 pieces) you have to set these constants as follows:
Toshihiro Shimizu 890ddd
	// cos_ang     ==> cos_60 = 0.5;
Toshihiro Shimizu 890ddd
	// sin_ang     ==> sin_60 = 0.5 * sqrt(3);
Toshihiro Shimizu 890ddd
	// tan_semiang ==> tan_30 = 0.57735026918962576450914878050196;
Toshihiro Shimizu 890ddd
	// N_QUAD                 = 6;
Toshihiro Shimizu 890ddd
	/* ---------------------------------------------------------------------------------- */
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Defines some useful constant to split the arc into arcs no TLonger than 'ang' degrees
Toshihiro Shimizu 890ddd
	// (the whole circumference will be splitted into 360/ang quadratic curves).
Toshihiro Shimizu 890ddd
	const double cos_ang = 0.5 * sqrt(2.0);
Toshihiro Shimizu 890ddd
	const double sin_ang = 0.5 * sqrt(2.0);
Toshihiro Shimizu 890ddd
	const double tan_semiang = 0.4142135623730950488016887242097;
Toshihiro Shimizu 890ddd
	const int N_QUAD = 8; // it's 360/ang
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// First of all, it computes the vectors from the center to the circumference,
Toshihiro Shimizu 890ddd
	// in Pstart and Pend, and their cross and dot products
Toshihiro Shimizu 890ddd
	TPointD Rstart = Pstart - Center;		 // its length is R (radius of the circle)
Toshihiro Shimizu 890ddd
	TPointD Rend = Pend - Center;			 // its length is R (radius of the circle)
Toshihiro Shimizu 890ddd
	double cross_prod = cross(Rstart, Rend); // it's Rstart x Rend
Toshihiro Shimizu 890ddd
	double dot_prod = Rstart * Rend;
Toshihiro Shimizu 890ddd
	const double sqr_radius = Rstart * Rstart;
Toshihiro Shimizu 890ddd
	TPointD aliasPstart = Pstart;
Toshihiro Shimizu 890ddd
	TQuadratic *quad;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	while ((cross_prod <= 0) || (dot_prod <= cos_ang * sqr_radius)) // the circular arc is TLonger
Toshihiro Shimizu 890ddd
																	// than a 'ang' degrees arc
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		if ((int)quadArray.size() == N_QUAD) // this is possible if Pstart or Pend is not onto the circumference
Toshihiro Shimizu 890ddd
			return;
Toshihiro Shimizu 890ddd
		TPointD Rstart_rot_ang(cos_ang * Rstart.x - sin_ang * Rstart.y,
Toshihiro Shimizu 890ddd
							   sin_ang * Rstart.x + cos_ang * Rstart.y);
Toshihiro Shimizu 890ddd
		TPointD Rstart_rot_90(-Rstart.y, Rstart.x);
Toshihiro Shimizu 890ddd
		quad = new TQuadratic(aliasPstart,
Toshihiro Shimizu 890ddd
							  aliasPstart + tan_semiang * Rstart_rot_90,
Toshihiro Shimizu 890ddd
							  Center + Rstart_rot_ang);
Toshihiro Shimizu 890ddd
		quadArray.push_back(quad);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// quad->computeMinStepAtNormalSize ();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// And moves anticlockwise the starting point on the circumference by 'ang' degrees
Toshihiro Shimizu 890ddd
		Rstart = Rstart_rot_ang;
Toshihiro Shimizu 890ddd
		aliasPstart = quad->getP2();
Toshihiro Shimizu 890ddd
		cross_prod = cross(Rstart, Rend); // it's Rstart x Rend
Toshihiro Shimizu 890ddd
		dot_prod = Rstart * Rend;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// after the rotation of 'ang' degrees, the remaining part of the arc could be a 0 degree
Toshihiro Shimizu 890ddd
		// arc, so it must stop and exit from the function
Toshihiro Shimizu 890ddd
		if ((cross_prod <= 0) && (dot_prod > 0.95 * sqr_radius))
Toshihiro Shimizu 890ddd
			return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if ((cross_prod > 0) && (dot_prod > 0)) // the last quadratic curve approximates an arc shorter than a 'ang' degrees arc
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		TPointD Rstart_rot_90(-Rstart.y, Rstart.x);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		double deg_index = (sqr_radius - dot_prod) / (sqr_radius + dot_prod);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		quad = new TQuadratic(aliasPstart,
Toshihiro Shimizu 890ddd
							  (deg_index < 0) ? 0.5 * (aliasPstart + Pend) : aliasPstart + sqrt(deg_index) * Rstart_rot_90,
Toshihiro Shimizu 890ddd
							  Pend);
Toshihiro Shimizu 890ddd
		quadArray.push_back(quad);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	} else // the last curve, already computed, is as TLong as a 'ang' degrees arc
Toshihiro Shimizu 890ddd
		quadArray.back()->setP2(Pend);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// copia arrayUp e arrayDown nel vettore dell'outline
Toshihiro Shimizu 890ddd
// se le dimensioni sono diverse il vettore con il numero
Toshihiro Shimizu 890ddd
// minore di quadratiche viene riempito con quadratiche degeneri
Toshihiro Shimizu 890ddd
// con i punti di controllo coincidenti nell'ultimo estremo valido
Toshihiro Shimizu 890ddd
void copy(/*std::ofstream& cout,*/
Shinya Kitaoka 3bfa54
		  const std::vector<tquadratic *=""> &arrayUp,</tquadratic>
Shinya Kitaoka 3bfa54
		  const std::vector<tquadratic *=""> &arrayDown,</tquadratic>
Toshihiro Shimizu 890ddd
		  outlineBoundary &ob)
Toshihiro Shimizu 890ddd
{
Shinya Kitaoka 12c444
	int minSize = std::min(arrayUp.size(), arrayDown.size());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	assert(minSize > 0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int i;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (i = 0; i < minSize; ++i) {
Toshihiro Shimizu 890ddd
		//cout<<"left: "<< *(arrayUp[i])<< "right: "<<*(arrayDown[i])<
Toshihiro Shimizu 890ddd
		//cout<"left: "<< arrayUp[i].getP0()<<", "arrayUp[i].getP1()<<", "arrayUp[i].getP2()<< "right: "<< << arrayDown[i].getP0()<<", "arrayDown[i].getP1()<<", "arrayDown[i].getP2()<
Toshihiro Shimizu 890ddd
		ob.push_back(outlineEdge(arrayUp[i], arrayDown[i]));
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	if (arrayUp.size() != arrayDown.size()) {
Shinya Kitaoka 3bfa54
		const std::vector<tquadratic *=""> &vMaxSize = arrayUp.size() > arrayDown.size() ? arrayUp : arrayDown;</tquadratic>
Shinya Kitaoka 3bfa54
		const std::vector<tquadratic *=""> &vMinSize = arrayUp.size() < arrayDown.size() ? arrayUp : arrayDown;</tquadratic>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		int delta = vMaxSize.size() - vMinSize.size();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (arrayUp.size() > arrayDown.size())
Toshihiro Shimizu 890ddd
			while (i < minSize + delta) {
Toshihiro Shimizu 890ddd
				//cout<<"left: "<< arrayUp[i]<< "right: "<< 0<
Toshihiro Shimizu 890ddd
				ob.push_back(outlineEdge(arrayUp[i], (TQuadratic *)0));
Toshihiro Shimizu 890ddd
				i++;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		else
Toshihiro Shimizu 890ddd
			while (i < minSize + delta) {
Toshihiro Shimizu 890ddd
				//cout<<"left: "<< 0 << "right: "<< arrayDown[i]<
Toshihiro Shimizu 890ddd
				ob.push_back(outlineEdge((TQuadratic *)0, arrayDown[i]));
Toshihiro Shimizu 890ddd
				i++;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
inline void changeQuadraticDirection(TQuadratic *q)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TPointD p = q->getP2();
Toshihiro Shimizu 890ddd
	q->setP2(q->getP0());
Toshihiro Shimizu 890ddd
	q->setP0(p);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// cambia il verso del vettore di quadratiche (vedi changeDirection di tstroke.cpp)
Toshihiro Shimizu 890ddd
void changeDirection(std::vector<tquadratic *=""> &array, bool onlyQuads = false)</tquadratic>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	UINT chunkCount = array.size();
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
		changeQuadraticDirection(array[to]);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	--chunkCount;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (i = 0; i < to; ++i) {
Toshihiro Shimizu 890ddd
		changeQuadraticDirection(array[i]);
Toshihiro Shimizu 890ddd
		changeQuadraticDirection(array[chunkCount - i]);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (!onlyQuads)
Toshihiro Shimizu 890ddd
			std::swap(array[i], array[chunkCount - i]);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// estrae i punti necessari a costruire la semicirconferenza
Toshihiro Shimizu 890ddd
// iniziale e finale di una curva cicciona
Toshihiro Shimizu 890ddd
TQuadratic getCircleQuarter(const TThickQuadratic *tq, int versus)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TQuadratic out;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TPointD v = versus ? -tq->getSpeed(0.0) : tq->getSpeed(1.0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (norm2(v))
Toshihiro Shimizu 890ddd
		v = normalize(v);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TPointD center = versus ? tq->getP0() : tq->getP2();
Toshihiro Shimizu 890ddd
	double radius = versus ? tq->getThickP0().thick : tq->getThickP2().thick;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	out.setP0(center + (versus ? rotate270(v) : rotate90(v)) * radius);
Toshihiro Shimizu 890ddd
	out.setP1(center + v * radius);
Toshihiro Shimizu 890ddd
	out.setP2(center + (versus ? rotate90(v) : rotate270(v)) * radius);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return out;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void drawQuadratic(const TQuadratic &quad, double pixelSize)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	double m_min_step_at_normal_size = localComputeStep(quad, pixelSize);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// It draws the curve as a linear piecewise approximation
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double invSqrtScale = 1.0;
Toshihiro Shimizu 890ddd
	// First of all, it computes the control circles of the curve in screen coordinates
Toshihiro Shimizu 890ddd
	TPointD scP0 = quad.getP0();
Toshihiro Shimizu 890ddd
	TPointD scP1 = quad.getP1();
Toshihiro Shimizu 890ddd
	TPointD scP2 = quad.getP2();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TPointD A = scP0 - 2 * scP1 + scP2;
Toshihiro Shimizu 890ddd
	TPointD B = scP0 - scP1;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double h;
Toshihiro Shimizu 890ddd
	h = invSqrtScale * m_min_step_at_normal_size;
Toshihiro Shimizu 890ddd
	double h2 = h * h;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TPointD P = scP0, D2 = 2 * h2 * A, D1 = A * h2 - 2 * B * h;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (h < 0 || isAlmostZero(h))
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	assert(h > 0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// It draws the whole curve, using forward differencing
Toshihiro Shimizu 890ddd
	glBegin(GL_LINE_STRIP); // The curve starts from scP0
Toshihiro Shimizu 890ddd
	glVertex2d(scP0.x, scP0.y);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (double t = h; t < 1; t = t + h) {
Toshihiro Shimizu 890ddd
		P = P + D1;
Toshihiro Shimizu 890ddd
		D1 = D1 + D2;
Toshihiro Shimizu 890ddd
		glVertex2d(P.x, P.y);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	glVertex2d(scP2.x, scP2.y); // The curve ends in scP2
Toshihiro Shimizu 890ddd
	glEnd();
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
void makeOutline(const TStroke *stroke, int startQuad, int endQuad,
Toshihiro Shimizu 890ddd
				 outlineBoundary &ob, double error2)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	//std::ofstream cout("c:\\temp\\outline.txt");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	assert(stroke);
Toshihiro Shimizu 890ddd
	assert(startQuad >= 0);
Toshihiro Shimizu 890ddd
	assert(endQuad < stroke->getChunkCount());
Toshihiro Shimizu 890ddd
	assert(startQuad <= endQuad);
Toshihiro Shimizu 890ddd
	TThickQuadratic *tq;
Toshihiro Shimizu 890ddd
	std::vector<tquadratic *=""> arrayUp, arrayDown;</tquadratic>
Toshihiro Shimizu 890ddd
	TQuadratic arc;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!stroke->getChunkCount())
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	//if (startQuad==0)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		const TThickQuadratic *tq = stroke->getChunk(startQuad);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// trova i punti sul cerchio che corrispondono
Toshihiro Shimizu 890ddd
		// a due fette di 90 gradi.
Toshihiro Shimizu 890ddd
		// Ritorna una quadratica invece di tre singoli punti solo per compattezza.
Toshihiro Shimizu 890ddd
		TQuadratic
Toshihiro Shimizu 890ddd
			arc = getCircleQuarter(tq, QUARTER_BEGIN);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// estrae le quadratiche che corrispondono ad i due archi...
Toshihiro Shimizu 890ddd
		splitCircularArcIntoQuadraticCurves(tq->getP0(), arc.getP0(), arc.getP1(), arrayUp);
Toshihiro Shimizu 890ddd
		// e le ordina in modo che l'outline sia composta sempre da
Toshihiro Shimizu 890ddd
		// una curva superiore ed una inferiore corrispondente
Toshihiro Shimizu 890ddd
		changeDirection(arrayUp);
Toshihiro Shimizu 890ddd
		splitCircularArcIntoQuadraticCurves(tq->getP0(), arc.getP1(), arc.getP2(), arrayDown);
Toshihiro Shimizu 890ddd
		changeDirection(arrayDown, true);
Toshihiro Shimizu 890ddd
		// copia le curve nell'outline; se gli array non hanno la stessa dimensione
Toshihiro Shimizu 890ddd
		//  quello con meno curve viene riempito con curve improprie
Toshihiro Shimizu 890ddd
		//  che hanno i punti di controllo coincidente con l'ultimo estremo valido
Toshihiro Shimizu 890ddd
		//cout<<"quads del semicerchio left:"<
Toshihiro Shimizu 890ddd
		copy(/*cout,  */ arrayUp, arrayDown, ob);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (int i = startQuad; i <= endQuad; ++i) {
Toshihiro Shimizu 890ddd
		tq = (TThickQuadratic *)stroke->getChunk(i);
Toshihiro Shimizu 890ddd
		TThickPoint p0 = tq->getThickP0();
Toshihiro Shimizu 890ddd
		TThickPoint p1 = tq->getThickP1();
Toshihiro Shimizu 890ddd
		TThickPoint p2 = tq->getThickP2();
Toshihiro Shimizu 890ddd
		if (p0.x == p1.x) {
Toshihiro Shimizu 890ddd
			if (p1.x == p2.x && ((p1.y > p0.y && p1.y > p2.y) || (p1.y < p0.y && p1.y < p2.y)))
Toshihiro Shimizu 890ddd
				tq = new TThickQuadratic(p0, 0.5 * (p0 + p1), p1);
Toshihiro Shimizu 890ddd
		} else if (p0.y == p1.y) {
Toshihiro Shimizu 890ddd
			if (p0.y == p2.y && ((p1.x > p0.x && p1.x > p2.x) || (p1.x < p0.x && p1.x < p2.x)))
Toshihiro Shimizu 890ddd
				tq = new TThickQuadratic(p0, 0.5 * (p0 + p1), p1);
Toshihiro Shimizu 890ddd
		} else {
Toshihiro Shimizu 890ddd
			double fac1 = 1.0 / (p0.x - p1.x);
Toshihiro Shimizu 890ddd
			double fac2 = 1.0 / (p0.y - p1.y);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			double aux1 = fac1 * (p2.x - p1.x);
Toshihiro Shimizu 890ddd
			double aux2 = fac2 * (p2.y - p1.y);
Toshihiro Shimizu 890ddd
			double aux3 = fac1 * (p0.x - p2.x);
Toshihiro Shimizu 890ddd
			double aux4 = fac2 * (p0.y - p2.y);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			if ((areAlmostEqual(aux1, aux2) && aux1 >= 0) ||
Toshihiro Shimizu 890ddd
				(areAlmostEqual(aux3, aux4) && aux3 >= 0 && aux3 <= 1))
Toshihiro Shimizu 890ddd
				tq = new TThickQuadratic(p0, 0.5 * (p0 + p1), p1);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		//cout<<"quad# "<
Toshihiro Shimizu 890ddd
		makeOutline(/*cout, */ ob, *tq, error2);
Toshihiro Shimizu 890ddd
		if (tq != stroke->getChunk(i))
Toshihiro Shimizu 890ddd
			delete tq;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	arrayUp.clear();
Toshihiro Shimizu 890ddd
	arrayDown.clear();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// come sopra ultimo pezzo di arco
Toshihiro Shimizu 890ddd
	//	if (endQuad==stroke->getChunkCount()-1)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		arc = getCircleQuarter(tq, QUARTER_END);
Toshihiro Shimizu 890ddd
		splitCircularArcIntoQuadraticCurves(tq->getP2(), arc.getP1(), arc.getP0(), arrayUp);
Toshihiro Shimizu 890ddd
		changeDirection(arrayUp);
Toshihiro Shimizu 890ddd
		splitCircularArcIntoQuadraticCurves(tq->getP2(), arc.getP2(), arc.getP1(), arrayDown);
Toshihiro Shimizu 890ddd
		changeDirection(arrayDown, true);
Toshihiro Shimizu 890ddd
		//cout<<"quads del semicerchio right:"<
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		copy(/*cout,*/ arrayUp, arrayDown, ob);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void drawOutline(const outlineBoundary &ob, double pixelSize)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	for (UINT i = 0; i < ob.size(); ++i) {
Toshihiro Shimizu 890ddd
		drawQuadratic(*ob[i].first, pixelSize);
Toshihiro Shimizu 890ddd
		drawQuadratic(*ob[i].second, pixelSize);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void computeOutlines(const TStroke *stroke, int startQuad, int endQuad,
Shinya Kitaoka 3bfa54
					 std::vector<tquadratic *=""> &quadArray, double error2)</tquadratic>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	outlineBoundary ob;
Toshihiro Shimizu 890ddd
	makeOutline(stroke, startQuad, endQuad, ob, error2);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	assert(quadArray.empty());
Toshihiro Shimizu 890ddd
	quadArray.resize(ob.size() * 2);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int i, count = 0;
Toshihiro Shimizu 890ddd
	for (i = 0; i < (int)ob.size(); i++)
Toshihiro Shimizu 890ddd
		if (ob[i].first)
Toshihiro Shimizu 890ddd
			quadArray[count++] = ob[i].first;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (i = (int)ob.size() - 1; i >= 0; i--)
Toshihiro Shimizu 890ddd
		if (ob[i].second)
Toshihiro Shimizu 890ddd
			quadArray[count++] = ob[i].second;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	quadArray.resize(count);
Toshihiro Shimizu 890ddd
	for (i = 0; i < (int)quadArray.size(); i++)
Toshihiro Shimizu 890ddd
		quadArray[i]->reverse();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	std::reverse(quadArray.begin(), quadArray.end());
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
// End Of File
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------