/** TODO: avoid recalculating when nothing changed */ Matrix44 Entity2D::GetCenterTransformationMatrix() { Matrix44 matrix = Matrix44::Identity; matrix.Scale(Vector3::Create(m_vScale.X, m_vScale.Y, 1.0f)); matrix.Rotate(Vector3::Create(0.0f, 0.0f, m_fRotation*Math::DegToRadFactor)); matrix.Translate(Vector3::Create(m_vPosition.X, m_vPosition.Y, 0.0f)); // TODO: use type checking at initialization time in AddChild() and only use static_cast here if(Entity2D* pEntity2D = GetAncestor<Entity2D>()) { matrix *= pEntity2D->GetTransformationMatrix(); } return matrix; }
//! returns true if the button is touched bool Button::IsTouched() const { Matrix44 transformation = Matrix44::Identity; transformation.Translate(-Vector3::Create(m_vCenter.X, m_vCenter.Y, 0.0f)); transformation.Scale(Vector3::Create(m_vScale.X, m_vScale.Y, 1.0f)); transformation.Rotate(Vector3::Create(0.0f, 0.0f, m_fRotation*Math::DegToRadFactor)); transformation.Translate(Vector3::Create(m_vOriginalPosition.X, m_vOriginalPosition.Y, 0.0f)); if(Entity2D* p2DEntity = GetAncestor<Entity2D>()) { transformation *= p2DEntity->GetTransformationMatrix(); } Matrix44 inverse; if(transformation.GetInverse(inverse)) { Vector2 vTouchPos = InputManager::Instance()->GetTouchState().vPosition; Vector3 invTouchPos3D = inverse.TransformVect(Vector3::Create(vTouchPos.X, vTouchPos.Y, 0.0f)); Vector2 vInvTouchPos(invTouchPos3D.X, invTouchPos3D.Y); return GetBoundingBox().Contains(vInvTouchPos); } return false; }
// Evolve rNode a specific time void Tree::Evolve(Node &rNode, double dTime) { dTime = fabs(dTime); if(dTime < DBL_EPSILON) return; // Nothing to evolve //advance branch color branchColor += Nucleotide::ColorInc; // Substitutions unsigned int uNuc = 0; for(vector<Sequence>::iterator it = rNode.m_vSections.begin(); it != rNode.m_vSections.end(); ++it) { for(Sequence::iterator jt = it->begin(); jt != it->end(); ++jt) { // Skip any position that is a deletion if(jt->IsDeleted()) continue; // Total Evolution Rate for the position double dTemp = dTime*jt->GetRate(); if(dTemp < DBL_EPSILON) continue; // Invariant Site // if dTemp is different from the previous one, recalculate probability matrix if(dTemp != m_dOldTime) { m_dOldTime = dTemp; Vector4 vec; vec[0] = exp(dTemp*m_vecL[0]); vec[1] = exp(dTemp*m_vecL[1]); vec[2] = exp(dTemp*m_vecL[2]); vec[3] = exp(dTemp*m_vecL[3]); Matrix44 mat; mat.Scale(vec, m_matU); m_matSubst.Multiply(m_matV, mat); for(Matrix44::Pos i=0;i<4;++i) { m_matSubst(i,1) += m_matSubst(i,0); m_matSubst(i,2) += m_matSubst(i,1); //m_matSubst(i,3) = 1.0; } } // get the base of the current nucleotide and pick new base unsigned int uBase = jt->GetBase(); dTemp = rand_real(); if(dTemp < m_matSubst(uBase, 0)) jt->SetBase(0); else if(dTemp < m_matSubst(uBase, 1)) jt->SetBase(1); else if(dTemp < m_matSubst(uBase, 2)) jt->SetBase(2); else jt->SetBase(3); ++uNuc; // Increase position } } // Indel formation via Gillespie Algorithm // Check whether Indels are off if(m_dLambdaDel+m_dLambdaIns < DBL_EPSILON) return; // Get current length Sequence::size_type uLength = rNode.SeqLength(); double dLength = (double)uLength; double dW = 1.0/m_funcRateSum(dLength); // Do indels for(double dt = rand_exp(dW); dt <= dTime; dt += rand_exp(dW)) { // insertion or deletion if(rand_bool(m_funcRateIns(dLength)*dW)) { //Insertion Sequence::size_type ul = m_pInsertionModel->RandSize(); Sequence::size_type uPos = (Sequence::size_type)rand_uint((uint32_t)uLength); // pos is in [0,L] // Construct sequence to be inserted Sequence seq; for(unsigned int uc = 0; uc < ul; ++uc) { Nucleotide nuc = RandomNucleotide(uc); nuc.SetColor(branchColor); seq.push_back(nuc); } // Find Position of Insertion Node::iterator itPos = rNode.SeqPos(uPos); if(itPos.first == rNode.m_vSections.end()) { // Insert at end of sequence uLength += rNode.m_vSections.back().Insertion( rNode.m_vSections.back().end(), seq.begin(), seq.end()); } else { // Insert inside sequence uLength += itPos.first->Insertion(itPos.second, seq.begin(), seq.end()); } } else if(uLength > 0) { // Deletion // Draw random size and random pos and rearrange Sequence::size_type ul = m_pDeletionModel->RandSize(); Sequence::size_type uPos = rand_uint((uint32_t)(uLength+ul-2)); Sequence::size_type uB = max(ul-1, uPos); Sequence::size_type uSize = min(ul-1+uLength, uPos+ul)-uB; // If GapLimits are on, only process deletion if it is completely inside the acceptance // region as defined by the GapLimit. Check points are at sequence positions 0-uKeepFlank and // uLength-1+uKeepFlank. These become 0-uKeepFlank+ul-1 and uLength-1+uKeepFlank+ul-1, // when shifted to "deletion space". if(m_uKeepFlank == 0 || ( (ul-1) < uPos+m_uKeepFlank && uPos < uLength-1+m_uKeepFlank ) ) { uB -= (ul-1); // Find deletion point Node::iterator itPos = rNode.SeqPos(uB); Sequence::size_type uTemp = uSize; uTemp -= itPos.first->Deletion(itPos.second, uTemp); // Delete uSize nucleotides begin sensitive to gaps that overlap sections for(++itPos.first; uSize && itPos.first != rNode.m_vSections.end(); ++itPos.first) uTemp -= itPos.first->Deletion(itPos.first->begin(), uTemp); uLength -= (uSize-uTemp); } } // update length dLength = (double)uLength; // new waiting time parameter dW = 1.0/m_funcRateSum(dLength); } }