コード例 #1
0
ファイル: intertwine.cpp プロジェクト: 4144/aseprite
void Intertwine::doPointshapePoint(int x, int y, ToolLoop* loop)
{
  Symmetry* symmetry = loop->getSymmetry();
  if (symmetry) {
    Point origin(loop->getCelOrigin());

    // Convert the point to the sprite position so we can apply the
    // symmetry transformation.
    Stroke main_stroke;
    main_stroke.addPoint(Point(x, y) + origin);

    Strokes strokes;
    symmetry->generateStrokes(main_stroke, strokes, loop);
    for (const auto& stroke : strokes) {
      // We call transformPoint() moving back each point to the cel
      // origin.
      loop->getPointShape()->transformPoint(
        loop,
        stroke[0].x - origin.x,
        stroke[0].y - origin.y);
    }
  }
  else {
    loop->getPointShape()->transformPoint(loop, x, y);
  }
}
コード例 #2
0
ファイル: Symmetry.cpp プロジェクト: vonwenm/Minisatid
SymmetryPropagator::SymmetryPropagator(PCSolver* solver, const Symmetry& sym)
		: 	Propagator(DEFAULTCONSTRID, solver, "symmetry propagator"),
			symmetrical(sym.getSymmetrical()),
			inverse(sym.getInverse()),
			nextToPropagate(0) {
	getPCSolver().accept(this);
	getPCSolver().accept(this, EV_BACKTRACK);
	getPCSolver().accept(this, EV_PROPAGATE);
	for (auto litpair : symmetrical) {
		getPCSolver().accept(this, litpair.first, FAST);
		// NOTE: negation of litpair.first is always in the symmetrical-map, so no need to add it twice.
	}
}
コード例 #3
0
ファイル: symmetrytest.cpp プロジェクト: phlipsi/sudoku
void test_symmetry(const Symmetry& s) {
  std::map<int, Symmetry::const_iterator> m;
  for (Symmetry::const_iterator i = s.begin(); i != s.end(); ++i) {
    for (unsigned int j = 0; j < 81; ++j) {
      if ((*i)[j]) {
        std::pair<std::map<int, Symmetry::const_iterator>::iterator, bool> result
          = m.insert(std::make_pair(j, i));
        assert(result.second);
      }
    }
  }
  for (unsigned int j = 0; j < 81; ++j) {
    std::map<int, Symmetry::const_iterator>::iterator it = m.find(j);
    assert(it != m.end());
  }
}
コード例 #4
0
ファイル: intertwine.cpp プロジェクト: blackmiaool/aseprite
void Intertwine::doPointshapePoint(int x, int y, ToolLoop* loop)
{
  Symmetry* symmetry = loop->getSymmetry();
  if (symmetry) {
    Stroke main_stroke;
    main_stroke.addPoint(gfx::Point(x, y));

    Strokes strokes;
    symmetry->generateStrokes(main_stroke, strokes);
    for (const auto& stroke : strokes)
      loop->getPointShape()->transformPoint(
        loop, stroke[0].x, stroke[0].y);
  }
  else {
    loop->getPointShape()->transformPoint(loop, x, y);
  }
}
コード例 #5
0
ファイル: generateCoiledCoils.cpp プロジェクト: Suncuss/mslib
int main(int argc, char *argv[]){
	// Option Parser
	Options opt = setupOptions(argc,argv);
	Transforms tr;

	// Super-helical Radius Loop
	for (double sr = opt.superHelicalRadius[0]; sr <= opt.superHelicalRadius[1]; sr += opt.superHelicalRadius[2]){

		// Alpha-helical Phase Angle Loop
		for (double aph = opt.alphaHelicalPhaseAngle[0]; aph < opt.alphaHelicalPhaseAngle[1];aph+=opt.alphaHelicalPhaseAngle[2]){

		  // Super-helical Pitch Angle loop added by David Slochower
		  for(double shpa = opt.superHelicalPitchAngle[0]; shpa < opt.superHelicalPitchAngle[1]; shpa+=opt.superHelicalPitchAngle[2]) {
		    double shPitch = (2*M_PI*sr)/tan(M_PI*shpa/180);

			// Generate a coiled helix
			CoiledCoils cc;
			// Values used for previous work: cc.northCoiledCoils(sr, 1.5232, shPitch, 2.25, opt.numberOfResidues, 103.195, aph);
			// March 31, 2010: Jason Donald
			// Hard code values of h (rise/residue) = 1.51, r1 (alpha-helical radius), and theta (alpha helical frequency)
                        // based on median values observed by Gevorg Grigoryan
			//cc.northCoiledCoils(sr, 1.51, shPitch, 2.26, opt.numberOfResidues, 102.8, aph);
			
			AtomPointerVector coil = cc.getCoiledCoil(sr, 1.51, shPitch, 2.26, 102.8, aph, 0.0,opt.numberOfResidues); 

			// Apply symmetry operations to create a bundle
			int C_axis = atoi(opt.symmetry.substr(1,(opt.symmetry.length()-1)).c_str());
			if (opt.symmetry.substr(0,1) == "C"){
				Symmetry sym;
				sym.applyCN(coil,C_axis);
	
				// Write out bundle
				char filename[80];
				sprintf(filename, "%s_%s_%03d_%05.2f_%05.2f_shp%05.2f.pdb", opt.name.c_str(),opt.symmetry.c_str(),opt.numberOfResidues, sr, aph, shpa);
			
				cout << "Writing "<<filename<<endl;
				PDBWriter pout;
				pout.open(filename);
				pout.write(sym.getAtomPointers());
				pout.close();
			}	
			else if (opt.symmetry.substr(0,1) == "D"){
				// Z Rotate 
				for (double spa = opt.superHelicalPhaseAngle[0]; spa < opt.superHelicalPhaseAngle[1]; spa += opt.superHelicalPhaseAngle[2]){
					coil.clearSavedCoor();
					coil.saveCoor("preSPA");

					Matrix zRot = CartesianGeometry::getZRotationMatrix(spa);
					//coil.rotate(zRot);
					tr.rotate(coil, zRot);
					
					// Z Trans
					for (double ztrans = opt.d2zTranslation[0];ztrans < opt.d2zTranslation[1]; ztrans += opt.d2zTranslation[2]){
						coil.saveCoor("preZtrans");

						CartesianPoint z(0,0,ztrans);
						//coil.translate(z);
						tr.translate(coil, z);

						Symmetry sym;
						sym.applyDN(coil,C_axis);
								
						// Write out bundle
						char filename[80];
						sprintf(filename, "%s_%s_%03d_%05.2f_%05.2f_shp%05.2f_%05.2f_%05.2f.pdb", opt.name.c_str(),opt.symmetry.c_str(),opt.numberOfResidues,sr, aph, shpa, spa, ztrans);
			
						cout << "Writing "<<filename<<endl;
						PDBWriter pout;
						pout.open(filename);
						pout.write(sym.getAtomPointers());
						pout.close();

						coil.applySavedCoor("preZtrans");
					} // Ztrans
					coil.applySavedCoor("preSPA");
				} // SHA
			} 
                }
           }
	}
}
コード例 #6
0
ファイル: interstitial.cpp プロジェクト: bbucior/mint
void Interstitial::voronoi(const ISO& iso, const Symmetry& symmetry, double tol)
{	
	
	// Clear space
	clear();
	
	// Output
	Output::newline();
	Output::print("Searching for interstitial sites using Voronoi method");
	Output::increase();
	
	// Set up image iterator
	ImageIterator images;
	images.setCell(iso.basis(), 12);
	
	// Loop over unique atoms in the structure
	int i, j, k;
	List<double> weights;
	OList<Vector3D> points;
	OList<Vector3D> vertices;
	Linked<Vector3D> intPoints;
	for (i = 0; i < symmetry.orbits().length(); ++i)
	{
		
		// Reset variables
		weights.length(0);
		points.length(0);
		vertices.length(0);
		
		// Loop over atoms in the structure
		for (j = 0; j < iso.atoms().length(); ++j)
		{
			for (k = 0; k < iso.atoms()[j].length(); ++k)
			{
				
				// Loop over images
				images.reset(symmetry.orbits()[i].atoms()[0]->fractional(), iso.atoms()[j][k].fractional());
				while (!images.finished())
				{
					
					// Skip if atoms are the same
					if (++images < 1e-8)
						continue;
					
					// Save current point
					points += symmetry.orbits()[i].atoms()[0]->cartesian() + images.cartVector();
					weights += 0.5;
				}
			}
		}
		
		// Calculate Voronoi volume
		symmetry.orbits()[i].atoms()[0]->cartesian().voronoi(points, weights, tol, &vertices);
		
		// Save points
		for (j = 0; j < vertices.length(); ++j)
		{
			intPoints += iso.basis().getFractional(vertices[j]);
			ISO::moveIntoCell(*intPoints.last());
		}
	}
	
	// Reduce points to unique ones
	bool found;
	double curDistance;
	Vector3D rotPoint;
	Vector3D equivPoint;
	Vector3D origin(0.0);
	Linked<double> distances;
	Linked<double>::iterator itDist;
	Linked<Vector3D>::iterator it;
	Linked<Vector3D> uniquePoints;
	Linked<Vector3D>::iterator itUnique;
	for (it = intPoints.begin(); it != intPoints.end(); ++it)
	{
		
		// Get current distance to origin
		curDistance = iso.basis().distance(*it, FRACTIONAL, origin, FRACTIONAL);
		
		// Loop over points that were already saved
		found = false;
		itDist = distances.begin();
		itUnique = uniquePoints.begin();
		for (; itDist != distances.end(); ++itDist, ++itUnique)
		{
			
			// Current points are not the same
			if (Num<double>::abs(curDistance - *itDist) <= tol)
			{
				if (iso.basis().distance(*it, FRACTIONAL, *itUnique, FRACTIONAL) <= tol)
				{
					found = true;
					break;
				}
			}
			
			// Loop over symmetry operations
			for (i = 0; i < symmetry.operations().length(); ++i)
			{
				
				// Loop over translations
				rotPoint = symmetry.operations()[i].rotation() * *it;
				for (j = 0; j < symmetry.operations()[i].translations().length(); ++j)
				{
					
					// Check if points are the same
					equivPoint = rotPoint;
					equivPoint += symmetry.operations()[i].translations()[j];
					if (iso.basis().distance(equivPoint, FRACTIONAL, *itUnique, FRACTIONAL) <= tol)
					{
						found = true;
						break;
					}
				}
				if (found)
					break;
			}
			if (found)
				break;
		}
		
		// Found a new point
		if (!found)
		{
			distances += curDistance;
			uniquePoints += *it;
		}
	}
	
	// Save unique points
	_sites.length(uniquePoints.length());
	for (i = 0, it = uniquePoints.begin(); it != uniquePoints.end(); ++i, ++it)
		_sites[i] = *it;
	
	// Output
	Output::newline();
	Output::print("Found ");
	Output::print(_sites.length());
	Output::print(" possible interstitial site");
	if (_sites.length() != 1)
		Output::print("s");
	Output::increase();
	for (i = 0; i < _sites.length(); ++i)
	{
		Output::newline();
		Output::print("Site ");
		Output::print(i+1);
		Output::print(":");
		for (j = 0; j < 3; ++j)
		{
			Output::print(" ");
			Output::print(_sites[i][j], 8);
		}
	}
	Output::decrease();
	
	// Output
	Output::decrease();
}
コード例 #7
0
ファイル: interstitial.cpp プロジェクト: bbucior/mint
void Interstitial::evaluate(const ISO& iso, const Symmetry& symmetry, int numPointsPerAtom, double tol, double scale)
{
	
	// Clear space
	clear();
	
	// Output
	Output::newline();
	Output::print("Searching for interstitial sites using ");
	Output::print(numPointsPerAtom);
	Output::print(" starting point");
	if (numPointsPerAtom != 1)
		Output::print("s");
	Output::print(" per atom and a scale of ");
	Output::print(scale);
	Output::increase();
	
	// Constants used in generating points on sphere around each atom
	double phiScale = Constants::pi * (3 - sqrt(5));
	double yScale = 2.0 / numPointsPerAtom;
	
	// Loop over unique atoms in the structure
	int i, j, k;
	int count = 0;
	double y;
	double r;
	double phi;
	double curDistance;
	double nearDistance;
	double startDistance;
	Vector3D curPoint;
	Linked<Vector3D > points;
	for (i = 0; i < symmetry.orbits().length(); ++i)
	{
		
		// Get the distance to nearest atom in the structure
		nearDistance = -1;
		for (j = 0; j < iso.atoms().length(); ++j)
		{
			for (k = 0; k < iso.atoms()[j].length(); ++k)
			{
				curDistance = iso.basis().distance(symmetry.orbits()[i].atoms()[0]->fractional(), FRACTIONAL, \
					iso.atoms()[j][k].fractional(), FRACTIONAL);
				if (curDistance > 0)
				{
					if ((nearDistance == -1) || (curDistance < nearDistance))
						nearDistance = curDistance;
				}
			}
		}
		
		// Set the starting distance away from atom
		startDistance = nearDistance / 2;
		
		// Loop over starting points
		for (j = 0; j < numPointsPerAtom; ++j)
		{
			
			// Check if running current point on current processor
			if ((++count + Multi::rank()) % Multi::worldSize() == 0)
			{
				
				// Get current starting point
				y = j * yScale - 1 + (yScale / 2);
				r = sqrt(1 - y*y);
				phi = j * phiScale; 
				curPoint.set(symmetry.orbits()[i].atoms()[0]->cartesian()[0] + startDistance*r*cos(phi), \
					symmetry.orbits()[i].atoms()[0]->cartesian()[1] + startDistance*y, \
					symmetry.orbits()[i].atoms()[0]->cartesian()[2] + startDistance*r*sin(phi));
				
				// Minimize the current point
				if (!minimizePoint(curPoint, iso, scale))
					continue;
				
				// Save current point in fractional coordinates
				points += iso.basis().getFractional(curPoint);
				ISO::moveIntoCell(*points.last());
			}
		}
	}
	
	// Reduce list of points to unique ones
	int m;
	bool found;
	int numLoops;
	Vector3D rotPoint;
	Vector3D equivPoint;
	Vector3D origin(0.0);
	Linked<double> distances;
	Linked<double>::iterator itDist;
	Linked<Vector3D> uniquePoints;
	Linked<Vector3D>::iterator it;
	Linked<Vector3D>::iterator itUnique;
	for (i = 0; i < Multi::worldSize(); ++i)
	{
		
		// Send number of points in list on current processor
		numLoops = points.length();
		Multi::broadcast(numLoops, i);
		
		// Loop over points
		if (i == Multi::rank())
			it = points.begin();
		for (j = 0; j < numLoops; ++j)
		{
			
			// Send out current point
			if (i == Multi::rank())
			{
				curPoint = *it;
				++it;
			}
			Multi::broadcast(curPoint, i);
			
			// Get current distance to origin
			curDistance = iso.basis().distance(curPoint, FRACTIONAL, origin, FRACTIONAL);
			
			// Loop over points that were already saved
			found = false;
			itDist = distances.begin();
			itUnique = uniquePoints.begin();
			for (; itDist != distances.end(); ++itDist, ++itUnique)
			{
				
				// Current points are not the same
				if (Num<double>::abs(curDistance - *itDist) <= tol)
				{
					if (iso.basis().distance(curPoint, FRACTIONAL, *itUnique, FRACTIONAL) <= tol)
					{
						found = true;
						break;
					}
				}
				
				// Loop over symmetry operations
				for (k = 0; k < symmetry.operations().length(); ++k)
				{
					
					// Loop over translations
					rotPoint = symmetry.operations()[k].rotation() * curPoint;
					for (m = 0; m < symmetry.operations()[k].translations().length(); ++m)
					{
						
						// Check if points are the same
						equivPoint = rotPoint;
						equivPoint += symmetry.operations()[k].translations()[m];
						if (iso.basis().distance(equivPoint, FRACTIONAL, *itUnique, FRACTIONAL) <= tol)
						{
							found = true;
							break;
						}
					}
					if (found)
						break;
				}
				if (found)
					break;
			}
			
			// Found a new point
			if (!found)
			{
				distances += curDistance;
				uniquePoints += curPoint;
			}
		}
	}
	
	// Save unique points
	_sites.length(uniquePoints.length());
	for (i = 0, it = uniquePoints.begin(); it != uniquePoints.end(); ++i, ++it)
		_sites[i] = *it;
	
	// Output
	Output::newline();
	Output::print("Found ");
	Output::print(_sites.length());
	Output::print(" possible interstitial site");
	if (_sites.length() != 1)
		Output::print("s");
	Output::increase();
	for (i = 0; i < _sites.length(); ++i)
	{
		Output::newline();
		Output::print("Site ");
		Output::print(i+1);
		Output::print(":");
		for (j = 0; j < 3; ++j)
		{
			Output::print(" ");
			Output::print(_sites[i][j], 8);
		}
	}
	Output::decrease();
	
	// Output
	Output::decrease();
}
コード例 #8
0
ファイル: testCoiledCoils.cpp プロジェクト: Suncuss/mslib
/******************************************
 *  
 *         =======  MAIN  =======
 *
 ******************************************/
int main(int argc, char *argv[]) {


        // Define Objects for the test
	CoiledCoils cc;
	CoiledCoilFitter ccf;
	PDBWriter pout;

	/******************************************************************************
	 *
	 *                   === GEVORG/CRICKS CC GENERATION ===
	 *
	 ******************************************************************************/





	//sys.writePdb(opt.fileName);
	cc.getCoiledCoilCricks(4.910, -4.027, -13.530, 2.267, 102.806, 149.984, 0.0, 26);
	AtomPointerVector cricks = cc.getAtomPointers();
	pout.open("/tmp/cricks.pdb");
	pout.write(cricks);
	pout.close();

	double shr = 4.910;
	double risePerRes = 1.51;
	double shp = 128.206;
	double ahr = 2.26;
	double ahp = 102.8;
	double ahphase = 149.984;
	double dZ  = 0.0; //meaningless parameter at the moment.
	cc.getCoiledCoil(shr, risePerRes, shp, ahr, ahp, ahphase, dZ, 26);
	AtomPointerVector norths = cc.getAtomPointers();
	pout.open("/tmp/norths.pdb");
	pout.write(norths);
	pout.close();

	Symmetry sym;
	sym.applyCN(norths,2);
	pout.open("/tmp/northC2.pdb");
	pout.write(sym.getAtomPointers());
	pout.close();

	System sys;
	sys.readPdb("/tmp/northC2.pdb");

	// Fitting procedure..

	// Add helix chain A
	ccf.addNextHelix(&sys.getChain("A").getAtomPointers());

	// Add helix chain B
	ccf.addNextHelix(&sys.getChain("B").getAtomPointers());	

	// Set symmetry
	ccf.setSymmetry("C");

	// Do fittin procedure
	ccf.fit();

	// Do something else..
	vector<double> params = ccf.getMinimizedParameters();

	if ( abs(params[0] - shr) > 0.1){
	  cerr << "ERROR Super-helical radius is off. Target = "<<shr<<" MinValue = "<<params[0]<<endl;
	} else if (abs(params[1] - risePerRes) > 0.1){
	  cerr << "ERROR RisePerRes is off. Target = "<<risePerRes<<" MinValue = "<<params[1]<<endl;
	} else if (abs(params[2] - shp) > 0.1){
	  cerr << "ERROR Super-helical pitch is off. Target = "<<shp<<" MinValue = "<<params[2]<<endl;
	} else if (abs(params[3] - ahr) > 0.1){
	  cerr << "ERROR Alpha-helical radius is off. Target = "<<ahr<<" MinValue = "<<params[3]<<endl;
	} else if (abs(params[4] - ahp) > 0.1){
	  cerr << "ERROR Alpha-helical pitch is off. Target = "<<ahp<<" MinValue = "<<params[4]<<endl;
	} else if (abs(params[5] - ahphase) > 0.1){
	  cerr << "ERROR Alpha-helical phase is off. Target = "<<ahphase<<" MinValue = "<<params[5]<<endl;
	} else if (abs(params[6] - dZ) > 0.1){
	  cerr << "ERROR deltaZ offset is off. Target = "<<dZ<<" MinValue = "<<params[6]<<endl;
	} else {
	  cout << "LEAD";
	}



}
コード例 #9
0
int main(int argc, char *argv[]) {

	// the program requires the location of the "exampleFiles" as an argument
	if (argc < 1) {
		cerr << "USAGE:\nexample_coiled_coil_and_symmetric_bundles" << endl;
		exit(0);
	}

	cout << "  ***************************************************************************************" << endl;
	cout << "" << endl;
	cout << "     How to generate coiled-coils in MSL (" << MslTools::getMSLversion() << ")   " << endl;
	cout << "" << endl;
	cout << "  ***************************************************************************************" << endl;
	cout << endl;
	cout << endl;

	// CoiledCoils object used to create a coiled helix (by a number of algorithms)
	CoiledCoils cc;

	// A super-helical radius
	double sr = 6.5;

	// An alpha-helical phase angle
	double aph = 0.0;

	// A super-helical pitch angle, and pitch distance
	double shpa = 190;
	double shPitch = (2*M_PI*sr)/tan(M_PI*shpa/180);

	// Hard code values of h (rise/residue) = 1.51, r1 (alpha-helical radius), and theta (alpha helical frequency)
	double risePerResidue = 1.51;

        // Use observed medians by Gevorg Grigoryan (Probing Deisgnability via a Generalized Model of Helical Bundle Geometry, JMB 2010)
	double alphaHelicalRadius = 2.26;
	double alphaHelicalFrequency = 102.8;

	// Number of residues in coil ( lets do 4 heptads = 28 residues )
	double numberOfResidues = 28;

	// Generate a coiled coil, using specified parameters
    	//cc.northCoiledCoils(sr, risePerResidue, shPitch, alphaHelicalRadius, numberOfResidues, alphaHelicalFrequency, aph);

	// dZ
	double dZ = 0.0;

	// Get the atoms from the CoiledCoils object back (this is a single coiled-coil helix)
	AtomPointerVector coil = cc.getCoiledCoil(sr, risePerResidue, shPitch, alphaHelicalRadius, alphaHelicalFrequency,dZ, aph,numberOfResidues);

	cout << "Writing /tmp/singleHelixCoil.pdb"<<endl;
	PDBWriter pout;
	pout.open("/tmp/singleHelixCoil.pdb");
	pout.write(coil);
	pout.close();

	// Create a symmtery object to generate a coiled bundle ( C4 symmetric )
	Symmetry sym;

	// Apply C4 to "coil"
	sym.applyCN(coil,4);
	cout << "Writing /tmp/C4HelixCoil.pdb"<<endl;
	pout.open("/tmp/C4HelixCoil.pdb");
	pout.write(sym.getAtomPointers());
	pout.close();

	
}
コード例 #10
0
void ToolLoopManager::doLoopStep(bool last_step)
{
  // Original set of points to interwine (original user stroke,
  // relative to sprite origin).
  Stroke main_stroke;
  if (!last_step)
    m_toolLoop->getController()->getStrokeToInterwine(m_stroke, main_stroke);
  else
    main_stroke = m_stroke;

  // Calculate the area to be updated in all document observers.
  Symmetry* symmetry = m_toolLoop->getSymmetry();
  Strokes strokes;
  if (symmetry)
    symmetry->generateStrokes(main_stroke, strokes, m_toolLoop);
  else
    strokes.push_back(main_stroke);

  calculateDirtyArea(strokes);

  // Validate source image area.
  if (m_toolLoop->getInk()->needsSpecialSourceArea()) {
    gfx::Region srcArea;
    m_toolLoop->getInk()->createSpecialSourceArea(m_dirtyArea, srcArea);
    m_toolLoop->validateSrcImage(srcArea);
  }
  else {
    m_toolLoop->validateSrcImage(m_dirtyArea);
  }

  m_toolLoop->getInk()->prepareForStrokes(m_toolLoop, strokes);

  // Invalidate destionation image areas.
  if (m_toolLoop->getTracePolicy() == TracePolicy::Last) {
    // Copy source to destination (reset the previous trace). Useful
    // for tools like Line and Ellipse (we kept the last trace only).
    m_toolLoop->invalidateDstImage();
  }
  else if (m_toolLoop->getTracePolicy() == TracePolicy::AccumulateUpdateLast) {
    // Revalidate only this last dirty area (e.g. pixel-perfect
    // freehand algorithm needs this trace policy to redraw only the
    // last dirty area, which can vary in one pixel from the previous
    // tool loop cycle).
    m_toolLoop->invalidateDstImage(m_dirtyArea);
  }

  m_toolLoop->validateDstImage(m_dirtyArea);

  // Join or fill user points
  if (!m_toolLoop->getFilled() || (!last_step && !m_toolLoop->getPreviewFilled()))
    m_toolLoop->getIntertwine()->joinStroke(m_toolLoop, main_stroke);
  else
    m_toolLoop->getIntertwine()->fillStroke(m_toolLoop, main_stroke);

  if (m_toolLoop->getTracePolicy() == TracePolicy::Overlap) {
    // Copy destination to source (yes, destination to source). In
    // this way each new trace overlaps the previous one.
    m_toolLoop->copyValidDstToSrcImage(m_dirtyArea);
  }

  if (!m_dirtyArea.isEmpty())
    m_toolLoop->updateDirtyArea();
}