phylo_tree_force.cpp
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:8k
源码类别:

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: phylo_tree_force.cpp,v $
  4.  * PRODUCTION Revision 1000.0  2004/06/01 21:31:04  gouriano
  5.  * PRODUCTION PRODUCTION: IMPORTED [GCC34_MSVC7] Dev-tree R1.4
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: phylo_tree_force.cpp,v 1000.0 2004/06/01 21:31:04 gouriano Exp $
  10.  * ===========================================================================
  11.  *
  12.  *                            PUBLIC DOMAIN NOTICE
  13.  *               National Center for Biotechnology Information
  14.  *
  15.  *  This software/database is a "United States Government Work" under the
  16.  *  terms of the United States Copyright Act.  It was written as part of
  17.  *  the author's official duties as a United States Government employee and
  18.  *  thus cannot be copyrighted.  This software/database is freely available
  19.  *  to the public for use. The National Library of Medicine and the U.S.
  20.  *  Government have not placed any restriction on its use or reproduction.
  21.  *
  22.  *  Although all reasonable efforts have been taken to ensure the accuracy
  23.  *  and reliability of the software and data, the NLM and the U.S.
  24.  *  Government do not and cannot warrant the performance or results that
  25.  *  may be obtained by using this software or data. The NLM and the U.S.
  26.  *  Government disclaim all warranties, express or implied, including
  27.  *  warranties of performance, merchantability or fitness for any particular
  28.  *  purpose.
  29.  *
  30.  *  Please cite the author in any work or product based on this material.
  31.  *
  32.  * ===========================================================================
  33.  *
  34.  * Authors:  Vladimir Tereshkov
  35.  *
  36.  * File Description: 
  37.  *      Force tree layout           
  38.  */
  39. #include <ncbi_pch.hpp>
  40. #include <corelib/ncbistl.hpp>
  41. #include <gui/opengl/glhelpers.hpp>
  42. #include <gui/graph/igraph_utils.hpp>
  43. #include <gui/widgets/phylo_tree/phylo_tree_render.hpp>
  44. #include <gui/widgets/phylo_tree/phylo_tree_force.hpp>
  45. #include <FL/Fl.H>
  46. #include <math.h>
  47. BEGIN_NCBI_SCOPE
  48. CPhyloForce::CPhyloForce()
  49. {    
  50.     // default values
  51.     m_SpringLength          = 40;    
  52.     m_Stiffness             = 100;
  53.     
  54.     m_ElectricalRepulsion   = 100;
  55.     m_Increment             = 0.1;
  56.     m_Initialized           = false;
  57. }
  58. CPhyloForce::~CPhyloForce()
  59. {
  60. }
  61. void  CPhyloForce::x_Layout(CPhyloTreeDataSource& ds)
  62. {
  63.     bool distMode = m_bDistMode;
  64.     m_bDistMode = false;
  65.     CPhyloRadial::x_Layout(ds);
  66.     m_bDistMode = distMode;
  67.     m_Hash = ds.GetHash();
  68.     Int4 leafs = ds.GetSize();
  69.     Int4 width = ds.GetWidth();
  70.     
  71.     m_xStep = (m_DimX - m_LeftMargin - m_RightMargin) /  width;
  72.     m_yStep = (m_DimY - m_TopMargin - m_BottomMargin) / (leafs-1); 
  73.     
  74.     
  75.     m_Radius = sqrt(m_xStep*m_xStep + m_yStep*m_yStep)/2;
  76.     m_StartDegree = 0.0;
  77.     m_ParentDegree = 0.0;
  78.     if (ds.GetNormDistance() > 0){        
  79.          m_NormDistance = m_ElectricalRepulsion / ds.GetNormDistance();
  80.     }
  81.     
  82.     for (int i=0; i<100; i++)   x_Calculate(ds.GetTree());  
  83.     // changing raster - x_Calculate for sure changed size in unpredictable way
  84.     TModelRect newRect = ds.GetBoundRect();
  85.     
  86.     m_RasterRect.Init(newRect.Left() - m_RightMargin, 
  87.                       newRect.Top() - m_TopMargin,                      
  88.                       newRect.Right() + m_RightMargin, 
  89.                       newRect.Bottom() + m_BottomMargin);                      
  90. }
  91. void  CPhyloForce::x_Render(CGlPane& pane, CPhyloTreeDataSource& ds)
  92. {    
  93.     pane.OpenOrtho();       
  94.     x_DrawTree( ds.GetTree() );       
  95.     pane.Close();   
  96. }
  97. void CPhyloForce:: x_Calculate(CPhyloTreeNode * node)
  98. {
  99.     double  xForce = 0;
  100.     double  yForce = 0;
  101.     double  distance;
  102.     double  xSpring = 0;
  103.     double  ySpring = 0;
  104.     double  xRepulsion = 0;
  105.     double  yRepulsion = 0;
  106.     
  107.     double  adjX;
  108.     double  adjY;
  109.     double  thisX = node->XY().first;
  110.     double  thisY = node->XY().second;
  111.     // two forces calculating at a same time    
  112.     for (CPhyloTreeDataSource::TNodeHash::iterator vx=m_Hash.begin(); vx!=m_Hash.end(); vx++){
  113.         CPhyloTreeNode * vertex = vx->second;
  114.         // skip itself
  115.         if (vertex == node) continue;
  116.     
  117.         adjX = vertex->XY().first;
  118.         adjY = vertex->XY().second;
  119.         // repulsion forces calculation
  120.         distance = sqrt((adjX - thisX)*(adjX - thisX) +  (adjY - thisY)*(adjY - thisY));
  121.         if( distance == 0 )   distance = 0.0001;   
  122.                 
  123.        // if (m_bDistMode){   
  124.          //   m_ElectricalRepulsion = vertex->GetDistance() * m_NormDistance;
  125.         //}
  126.         xRepulsion += ( m_ElectricalRepulsion / distance ) * (( thisX - adjX ) / ( distance ));        
  127.         yRepulsion += ( m_ElectricalRepulsion / distance ) *  (( thisY - adjY ) / ( distance ));
  128.         // if vertex is adjucent, calculate spring force        
  129.         if ((vertex->GetParent() && (vertex->GetParent()->GetValue()==node)) ||
  130.             (node->GetParent() && (node->GetParent()->GetValue()==vertex))){                
  131.             xSpring += m_Stiffness * log( distance / m_SpringLength ) * (( thisX - adjX ) / ( distance ));
  132.             ySpring += m_Stiffness * log( distance / m_SpringLength ) *   (( thisY - adjY ) / ( distance ));
  133.         }
  134.     }
  135.         
  136.     // resulting force       
  137.     xForce = -xSpring + xRepulsion;
  138.     yForce = -ySpring + yRepulsion;
  139.     // altering positions
  140.     node->XY().first  += ( xForce * m_Increment );
  141.     node->XY().second += ( yForce * m_Increment );
  142.    
  143.     if (!node->IsLeaf())  {                     
  144.         for(CPhyloTreeNode::TNodeList_I  it = node->SubNodeBegin();  it != node->SubNodeEnd(); it++ )  {                          
  145.             x_Calculate((*it)->GetValue());                    
  146.         }
  147.     }        
  148. }
  149. void CPhyloForce :: x_DrawTree(CPhyloTreeNode * node)
  150. {      
  151.     // label
  152.     if (m_pLabelFont && node->IsLeaf()){
  153.         CGlPoint<int> labelPos(node->GetValue()->XY().first, node->GetValue()->XY().second);
  154.         m_Label.Render(*m_pPane, labelPos, node->GetLabel(), node->GetSelected(), (node->GetAngle() < -1.57 ||  node->GetAngle()>1.57));
  155.     }
  156.     
  157.     // drawing leaf node                             
  158.     if (node->GetParent()){
  159.         x_RenderLine(node->GetParent()->GetValue()->XY().first + m_LineWidth, node->GetParent()->GetValue()->XY().second,
  160.                      node->GetValue()->XY().first, node->GetValue()->XY().second, m_LineWidth, node->GetSelected()?m_LineSelColor:m_LineColor, node->GetSelected()?m_LineSelHiColor:m_LineHiColor);
  161.     }
  162.     for(CPhyloTreeNode::TNodeList_I  it = node->SubNodeBegin();  it != node->SubNodeEnd(); it++ )  x_DrawTree((*it)->GetValue());         
  163.     x_RenderNode(node->GetValue()->XY().first, node->GetValue()->XY().second, m_NodeSize,   node->GetSelected()?m_NodeSelColor:m_NodeColor);
  164. }
  165.     
  166. void CPhyloForce :: x_CountLeafs(CPhyloTreeNode * node, Int4 & lfCount)
  167. {     
  168.     if (node->IsLeaf()) lfCount++;
  169.     for (CPhyloTreeNode::TNodeList_I  it = node->SubNodeBegin();  it != node->SubNodeEnd(); it++) x_CountLeafs((*it)->GetValue(), lfCount);    
  170. }
  171. string CPhyloForce::GetDescription(void)
  172. {
  173.     return "Force Layout";
  174. }
  175. END_NCBI_SCOPE
  176. /*
  177.  * ===========================================================================
  178.  * $Log: phylo_tree_force.cpp,v $
  179.  * Revision 1000.0  2004/06/01 21:31:04  gouriano
  180.  * PRODUCTION: IMPORTED [GCC34_MSVC7] Dev-tree R1.4
  181.  *
  182.  * Revision 1.4  2004/05/21 22:27:54  gorelenk
  183.  * Added PCH ncbi_pch.hpp
  184.  *
  185.  * Revision 1.3  2004/05/20 15:30:49  tereshko
  186.  * Typo fixed
  187.  *
  188.  * Revision 1.2  2004/05/11 20:53:12  tereshko
  189.  * Work in progress
  190.  *
  191.  * Revision 1.1  2004/05/06 19:41:48  tereshko
  192.  * Initial revision
  193.  *
  194.  * ===========================================================================
  195.  */