Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "tools/tool.h"
Toshihiro Shimizu 890ddd
#include "tools/toolutils.h"
Toshihiro Shimizu 890ddd
#include "tools/cursors.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "tstroke.h"
Toshihiro Shimizu 890ddd
#include "tstrokeutil.h"
Toshihiro Shimizu 890ddd
#include "tstrokedeformations.h"
Toshihiro Shimizu 890ddd
#include "tmathutil.h"
Toshihiro Shimizu 890ddd
#include "tproperty.h"
Toshihiro Shimizu 890ddd
#include "drawutil.h"
Toshihiro Shimizu 890ddd
#include "tcurveutil.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "toonz/tobjecthandle.h"
Toshihiro Shimizu 890ddd
#include "toonz/txshlevelhandle.h"
Toshihiro Shimizu 890ddd
#include "toonz/tstageobject.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
using namespace ToolUtils;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// For Qt translation support
Toshihiro Shimizu 890ddd
#include <qcoreapplication></qcoreapplication>
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
 Controlla se il primo punto della prima sotto_stroke
Toshihiro Shimizu 890ddd
 e' interno al cerchio, nel caso la stroke successiva
Toshihiro Shimizu 890ddd
 deve essere quella esterna e cosi' via, basta allora
Toshihiro Shimizu 890ddd
 fissare un contatore in modo da prendere le stroke
Toshihiro Shimizu 890ddd
 alternativamente (interne/esterne).
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
void selectStrokeToMove(const ArrayOfStroke &v,
Toshihiro Shimizu 890ddd
						const TPointD ¢er,
Toshihiro Shimizu 890ddd
						double radius,
Toshihiro Shimizu 890ddd
						ArrayOfStroke &toMove)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (v.empty())
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	UINT counter;
Toshihiro Shimizu 890ddd
	if (tdistance2(v.front()->getPoint(0), center) < sq(radius))
Toshihiro Shimizu 890ddd
		counter = 0;
Toshihiro Shimizu 890ddd
	else
Toshihiro Shimizu 890ddd
		counter = 1;
Toshihiro Shimizu 890ddd
	do {
Toshihiro Shimizu 890ddd
		toMove.push_back(v[counter]);
Toshihiro Shimizu 890ddd
		counter += 2;
Toshihiro Shimizu 890ddd
	} while (counter < v.size());
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
/*
Toshihiro Shimizu 890ddd
inline  double computeStep(const TQuadratic& quad, double invOfPixelSize)
Toshihiro Shimizu 890ddd
{  
Toshihiro Shimizu 890ddd
  double step = std::numeric_limits<double>::max();</double>
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
  double  A_len = norm(A);
Toshihiro Shimizu 890ddd
  if (A_len > 0)  step = TConsts::sqrt2 * sqrt(invOfPixelSize/A_len); 
Toshihiro Shimizu 890ddd
  
Toshihiro Shimizu 890ddd
  return  step;
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 = computeStep(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
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
} // namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
// MagnetTool
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class MagnetTool : public TTool
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	Q_DECLARE_TR_FUNCTIONS(MagnetTool)
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool m_active;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TPointD
Toshihiro Shimizu 890ddd
		m_startingPos;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TPointD
Toshihiro Shimizu 890ddd
		m_oldPos,
Toshihiro Shimizu 890ddd
		m_pointAtMouseDown,
Toshihiro Shimizu 890ddd
		m_pointAtMove;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	DoublePair m_extremes;
Toshihiro Shimizu 890ddd
	int m_cursorId;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double m_pointSize;
Toshihiro Shimizu 890ddd
	TUndo *m_undo;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	typedef struct {
Toshihiro Shimizu 890ddd
		TStroke *m_parent;
Toshihiro Shimizu 890ddd
		ArrayOfStroke m_splitted;
Toshihiro Shimizu 890ddd
		ArrayOfStroke m_splittedToMove;
Toshihiro Shimizu 890ddd
	} strokeCollection;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 3bfa54
	std::vector<strokecollection> m_strokeToModify;</strokecollection>
Toshihiro Shimizu 890ddd
	//vector<strokeinfo>  m_info;</strokeinfo>
Shinya Kitaoka 3bfa54
	std::vector<tstroke *=""> m_strokeHit, m_oldStrokesArray;</tstroke>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 3bfa54
	std::vector<int> m_changedStrokes;</int>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 3bfa54
	std::vector<std::vector<int> *> m_hitStrokeCorners, m_strokeToModifyCorners;</std::vector<int>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TDoubleProperty m_toolSize;
Toshihiro Shimizu 890ddd
	TPropertyGroup m_prop;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	MagnetTool()
Toshihiro Shimizu 890ddd
		: TTool("T_Magnet"), m_active(false), m_pointSize(-1), m_oldStrokesArray(), m_toolSize("Size:", 0, 100, 20) // W_ToolOptions_MagnetTool
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		bind(TTool::Vectors);
Toshihiro Shimizu 890ddd
		m_prop.bind(m_toolSize);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	ToolType getToolType() const { return TTool::LevelWriteTool; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void updateTranslation()
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		m_toolSize.setQStringName(tr("Size:"));
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void onEnter()
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		if ((TVectorImageP)getImage(false))
Toshihiro Shimizu 890ddd
			m_cursorId = ToolCursor::MagnetCursor;
Toshihiro Shimizu 890ddd
		else
Toshihiro Shimizu 890ddd
			m_cursorId = ToolCursor::CURSOR_NO;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		double x = m_toolSize.getValue();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		double minRange = 1;
Toshihiro Shimizu 890ddd
		double maxRange = 100;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		double minSize = 10;
Toshihiro Shimizu 890ddd
		double maxSize = 100;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		m_pointSize = (x - minRange) / (maxRange - minRange) * (maxSize - minSize) + minSize;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void onLeave()
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		m_pointSize = -1;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void leftButtonDown(const TPointD &pos, const TMouseEvent &e)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		TPointD p(pos);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		m_oldPos = pos;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		m_pointAtMouseDown = p;
Toshihiro Shimizu 890ddd
		m_startingPos = p;
Toshihiro Shimizu 890ddd
		m_active = false;
Toshihiro Shimizu 890ddd
		TVectorImageP vi = TImageP(getImage(true));
Toshihiro Shimizu 890ddd
		if (!vi)
Toshihiro Shimizu 890ddd
			return;
Toshihiro Shimizu 890ddd
		QMutexLocker lock(vi->getMutex());
Toshihiro Shimizu 890ddd
		m_active = true;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		m_pointAtMove = m_pointAtMouseDown = p;
Toshihiro Shimizu 890ddd
		m_strokeHit.clear();
Toshihiro Shimizu 890ddd
		m_changedStrokes.clear();
Toshihiro Shimizu 890ddd
		m_strokeToModify.clear();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 3bfa54
		std::vector<tstroke *=""> strokeUndo;</tstroke>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		TStroke *ref;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		m_hitStrokeCorners.clear();
Toshihiro Shimizu 890ddd
		m_strokeToModifyCorners.clear();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		UINT i = 0;
Toshihiro Shimizu 890ddd
		for (; i < vi->getStrokeCount(); ++i) {
Toshihiro Shimizu 890ddd
			if (!vi->inCurrentGroup(i))
Toshihiro Shimizu 890ddd
				continue;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			TStroke *stroke = vi->getStroke(i);
Toshihiro Shimizu 890ddd
			ref = stroke;
Toshihiro Shimizu 890ddd
			//  calcola le intersezioni
Shinya Kitaoka 3bfa54
			std::vector<double> intersections;</double>
Toshihiro Shimizu 890ddd
			intersect(*ref, p, m_pointSize, intersections);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			if (intersections.empty()) {
Toshihiro Shimizu 890ddd
				if (increaseControlPoints(*ref,
Toshihiro Shimizu 890ddd
										  TStrokePointDeformation(p, m_pointSize))) {
Toshihiro Shimizu 890ddd
					m_changedStrokes.push_back(i);
Toshihiro Shimizu 890ddd
					m_strokeHit.push_back(ref);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 3bfa54
					std::vector<int> *corners = new std::vector<int>;</int></int>
Toshihiro Shimizu 890ddd
					corners->push_back(0);
Toshihiro Shimizu 890ddd
					detectCorners(ref, 20, *corners);
Toshihiro Shimizu 890ddd
					corners->push_back(ref->getChunkCount());
Toshihiro Shimizu 890ddd
					m_hitStrokeCorners.push_back(corners);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					ref->disableComputeOfCaches();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					strokeUndo.push_back(ref);
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			} else {
Toshihiro Shimizu 890ddd
				strokeUndo.push_back(ref);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				MagnetTool::strokeCollection sc;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				sc.m_parent = ref;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				splitStroke(*sc.m_parent, intersections, sc.m_splitted);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				selectStrokeToMove(sc.m_splitted,
Toshihiro Shimizu 890ddd
								   p,
Toshihiro Shimizu 890ddd
								   m_pointSize,
Toshihiro Shimizu 890ddd
								   sc.m_splittedToMove);
Toshihiro Shimizu 890ddd
				for (UINT ii = 0; ii < sc.m_splittedToMove.size(); ++ii) {
Toshihiro Shimizu 890ddd
					TStroke *temp = sc.m_splittedToMove[ii];
Toshihiro Shimizu 890ddd
					bool test = increaseControlPoints(*temp, TStrokePointDeformation(p, m_pointSize));
Toshihiro Shimizu 890ddd
					assert(test);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 3bfa54
					std::vector<int> *corners = new std::vector<int>;</int></int>
Toshihiro Shimizu 890ddd
					corners->push_back(0);
Toshihiro Shimizu 890ddd
					detectCorners(temp, 20, *corners);
Toshihiro Shimizu 890ddd
					corners->push_back(temp->getChunkCount());
Toshihiro Shimizu 890ddd
					m_strokeToModifyCorners.push_back(corners);
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				m_strokeToModify.push_back(sc);
Toshihiro Shimizu 890ddd
				m_changedStrokes.push_back(i);
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		m_oldStrokesArray.resize(m_changedStrokes.size());
Toshihiro Shimizu 890ddd
		for (i = 0; i < m_changedStrokes.size(); i++)
Toshihiro Shimizu 890ddd
			m_oldStrokesArray[i] = new TStroke(*(vi->getStroke(m_changedStrokes[i])));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (!strokeUndo.empty()) {
Toshihiro Shimizu 890ddd
			if (TTool::getApplication()->getCurrentObject()->isSpline())
Toshihiro Shimizu 890ddd
				m_undo = new UndoPath(getXsheet()->getStageObject(getObjectId())->getSpline());
Toshihiro Shimizu 890ddd
			else {
Toshihiro Shimizu 890ddd
				TXshSimpleLevel *sl = TTool::getApplication()->getCurrentLevel()->getSimpleLevel();
Toshihiro Shimizu 890ddd
				assert(sl);
Toshihiro Shimizu 890ddd
				TFrameId id = getCurrentFid();
Toshihiro Shimizu 890ddd
				m_undo = new UndoModifyListStroke(sl, id, strokeUndo);
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		invalidate();
Toshihiro Shimizu 890ddd
		// vi->validateRegionEdges(ref, true);
Toshihiro Shimizu 890ddd
	};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void leftButtonDrag(const TPointD &p, const TMouseEvent &)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (!m_active)
Toshihiro Shimizu 890ddd
			return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		//      double dx = p.x - m_pointAtMouseDown.x;
Toshihiro Shimizu 890ddd
		double pixelSize = getPixelSize();
Toshihiro Shimizu 890ddd
		if (tdistance2(p, m_oldPos) < 9.0 * pixelSize * pixelSize)
Toshihiro Shimizu 890ddd
			return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		m_oldPos = p;
Toshihiro Shimizu 890ddd
		m_pointAtMouseDown = p;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		//double sc = exp(0.001 * (double)dx);
Toshihiro Shimizu 890ddd
		TVectorImageP vi = TImageP(getImage(true));
Toshihiro Shimizu 890ddd
		if (!vi)
Toshihiro Shimizu 890ddd
			return;
Toshihiro Shimizu 890ddd
		QMutexLocker lock(vi->getMutex());
Toshihiro Shimizu 890ddd
		TPointD
Toshihiro Shimizu 890ddd
			offset = p - m_pointAtMove;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		/*
Toshihiro Shimizu 890ddd
      if( tdistance2(m_pointAtMouseDown, p ) > sq(m_pointSize * 0.5) ) // reincremento
Toshihiro Shimizu 890ddd
      {
Toshihiro Shimizu 890ddd
      leftButtonUp(p);
Toshihiro Shimizu 890ddd
      lefrightButtonDown(p);
Toshihiro Shimizu 890ddd
      }
Toshihiro Shimizu 890ddd
    */
Toshihiro Shimizu 890ddd
		UINT i, j;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		for (i = 0; i < m_strokeHit.size(); ++i)
Toshihiro Shimizu 890ddd
			modifyControlPoints(*m_strokeHit[i],
Toshihiro Shimizu 890ddd
								TStrokePointDeformation(offset, m_pointAtMouseDown, m_pointSize * 0.7));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		for (i = 0; i < m_strokeToModify.size(); ++i)
Toshihiro Shimizu 890ddd
			for (j = 0; j < m_strokeToModify[i].m_splittedToMove.size(); ++j) {
Toshihiro Shimizu 890ddd
				TStroke *temp = m_strokeToModify[i].m_splittedToMove[j];
Toshihiro Shimizu 890ddd
				modifyControlPoints(*temp, TStrokePointDeformation(offset, m_pointAtMouseDown, m_pointSize * 0.7));
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		m_pointAtMove = p;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		invalidate();
Toshihiro Shimizu 890ddd
	};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void mouseMove(const TPointD &p, const TMouseEvent &e)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		m_pointAtMove = p;
Toshihiro Shimizu 890ddd
		double pixelSize = getPixelSize();
Toshihiro Shimizu 890ddd
		if (tdistance2(p, m_oldPos) < 9.0 * pixelSize * pixelSize)
Toshihiro Shimizu 890ddd
			return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		m_oldPos = p;
Toshihiro Shimizu 890ddd
		invalidate();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void leftButtonUp(const TPointD &, const TMouseEvent &)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		if (!m_active)
Toshihiro Shimizu 890ddd
			return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		m_active = false;
Toshihiro Shimizu 890ddd
		m_pointAtMouseDown = m_pointAtMove = TConsts::napd;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		TStroke *ref;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		TVectorImageP vi = TImageP(getImage(true));
Toshihiro Shimizu 890ddd
		if (!vi)
Toshihiro Shimizu 890ddd
			return;
Toshihiro Shimizu 890ddd
		QMutexLocker lock(vi->getMutex());
Toshihiro Shimizu 890ddd
		UINT i, j;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		for (i = 0; i < m_strokeHit.size(); ++i) {
Toshihiro Shimizu 890ddd
			ref = m_strokeHit[i];
Toshihiro Shimizu 890ddd
			ref->enableComputeOfCaches();
Toshihiro Shimizu 890ddd
			ref->reduceControlPoints(getPixelSize() * ReduceControlPointCorrection, *(m_hitStrokeCorners[i]));
Toshihiro Shimizu 890ddd
			// vi->validateRegionEdges(ref, false);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		clearPointerContainer(m_hitStrokeCorners);
Toshihiro Shimizu 890ddd
		m_hitStrokeCorners.clear();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		UINT count = 0;
Toshihiro Shimizu 890ddd
		for (i = 0; i < m_strokeToModify.size(); ++i) {
Toshihiro Shimizu 890ddd
			// recupero la stroke collection
Toshihiro Shimizu 890ddd
			MagnetTool::strokeCollection &sc = m_strokeToModify[i];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			for (j = 0; j < sc.m_splittedToMove.size(); ++j) {
Toshihiro Shimizu 890ddd
				ref = sc.m_splittedToMove[j];
Toshihiro Shimizu 890ddd
				ref->enableComputeOfCaches();
Toshihiro Shimizu 890ddd
				ref->reduceControlPoints(getPixelSize() * ReduceControlPointCorrection, *(m_strokeToModifyCorners[count++]));
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			// ricostruisco una stroke con quella data
Toshihiro Shimizu 890ddd
			ref = merge(sc.m_splitted);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			if (sc.m_parent->isSelfLoop()) {
Toshihiro Shimizu 890ddd
				int cpCount = ref->getControlPointCount();
Toshihiro Shimizu 890ddd
				TThickPoint p1 = ref->getControlPoint(0);
Toshihiro Shimizu 890ddd
				TThickPoint p2 = ref->getControlPoint(cpCount - 1);
Toshihiro Shimizu 890ddd
				TThickPoint midP = (p1 + p2) * 0.5;
Toshihiro Shimizu 890ddd
				ref->setControlPoint(0, midP);
Toshihiro Shimizu 890ddd
				ref->setControlPoint(cpCount - 1, midP);
Toshihiro Shimizu 890ddd
				ref->setSelfLoop(true);
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			sc.m_parent->swapGeometry(*ref);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			delete ref;							  // elimino la curva temporanea
Toshihiro Shimizu 890ddd
			clearPointerContainer(sc.m_splitted); // pulisco le stroke trovate con lo split
Toshihiro Shimizu 890ddd
			sc.m_splittedToMove.clear();		  // pulisco il contenitore ( le stroke
Toshihiro Shimizu 890ddd
												  // che erano contenute qua sono state
Toshihiro Shimizu 890ddd
												  // eliminate nella clearPointer....
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		clearPointerContainer(m_strokeToModifyCorners);
Toshihiro Shimizu 890ddd
		m_strokeToModifyCorners.clear();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		for (i = 0; i < vi->getStrokeCount(); ++i) {
Toshihiro Shimizu 890ddd
			ref = vi->getStroke(i);
Toshihiro Shimizu 890ddd
			ref->invalidate();
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		vi->notifyChangedStrokes(m_changedStrokes, m_oldStrokesArray);
Toshihiro Shimizu 890ddd
		notifyImageChanged();
Toshihiro Shimizu 890ddd
		if (m_undo)
Toshihiro Shimizu 890ddd
			TUndoManager::manager()->add(m_undo);
Toshihiro Shimizu 890ddd
		m_undo = 0;
Toshihiro Shimizu 890ddd
		clearPointerContainer(m_oldStrokesArray);
Toshihiro Shimizu 890ddd
		m_oldStrokesArray.clear();
Toshihiro Shimizu 890ddd
		invalidate();
Toshihiro Shimizu 890ddd
	};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void draw()
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		TVectorImageP vi = TImageP(getImage(true));
Toshihiro Shimizu 890ddd
		if (!vi)
Toshihiro Shimizu 890ddd
			return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		//TAffine viewMatrix = getViewer()->getViewMatrix();
Toshihiro Shimizu 890ddd
		//glPushMatrix();
Toshihiro Shimizu 890ddd
		//tglMultMatrix(viewMatrix);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (m_pointSize > 0) {
Toshihiro Shimizu 890ddd
			tglColor(TPixel32::Red);
Toshihiro Shimizu 890ddd
			tglDrawCircle(m_pointAtMove, m_pointSize);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (!m_active) {
Toshihiro Shimizu 890ddd
			//glPopMatrix();
Toshihiro Shimizu 890ddd
			return;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		TPointD delta = m_pointAtMouseDown - m_startingPos;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		//    glPushMatrix();
Toshihiro Shimizu 890ddd
		//tglMultMatrix(m_referenceMatrix);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (!m_strokeHit.empty())
Toshihiro Shimizu 890ddd
			for (UINT i = 0; i < m_strokeHit.size(); ++i)
Toshihiro Shimizu 890ddd
				drawStrokeCenterline(*m_strokeHit[i], getPixelSize());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		tglColor(TPixel32::Red);
Toshihiro Shimizu 890ddd
		UINT i, j;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		for (i = 0; i < m_strokeToModify.size(); ++i)
Toshihiro Shimizu 890ddd
			for (j = 0; j < m_strokeToModify[i].m_splittedToMove.size(); ++j) {
Toshihiro Shimizu 890ddd
				TStroke *temp = m_strokeToModify[i].m_splittedToMove[j];
Toshihiro Shimizu 890ddd
				drawStrokeCenterline(*temp, getPixelSize());
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		//    glPopMatrix();
Toshihiro Shimizu 890ddd
		//glPopMatrix();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void onActivate()
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		//        getApplication()->editImageOrSpline();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TPropertyGroup *getProperties(int targetType)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		return &m_prop;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int getCursorId() const { return m_cursorId; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
} magnetTool;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//TTool *getMagnetTool() {return &magnetTool;}