phylo_tree_force.cpp
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:8k
- /*
- * ===========================================================================
- * PRODUCTION $Log: phylo_tree_force.cpp,v $
- * PRODUCTION Revision 1000.0 2004/06/01 21:31:04 gouriano
- * PRODUCTION PRODUCTION: IMPORTED [GCC34_MSVC7] Dev-tree R1.4
- * PRODUCTION
- * ===========================================================================
- */
- /* $Id: phylo_tree_force.cpp,v 1000.0 2004/06/01 21:31:04 gouriano Exp $
- * ===========================================================================
- *
- * PUBLIC DOMAIN NOTICE
- * National Center for Biotechnology Information
- *
- * This software/database is a "United States Government Work" under the
- * terms of the United States Copyright Act. It was written as part of
- * the author's official duties as a United States Government employee and
- * thus cannot be copyrighted. This software/database is freely available
- * to the public for use. The National Library of Medicine and the U.S.
- * Government have not placed any restriction on its use or reproduction.
- *
- * Although all reasonable efforts have been taken to ensure the accuracy
- * and reliability of the software and data, the NLM and the U.S.
- * Government do not and cannot warrant the performance or results that
- * may be obtained by using this software or data. The NLM and the U.S.
- * Government disclaim all warranties, express or implied, including
- * warranties of performance, merchantability or fitness for any particular
- * purpose.
- *
- * Please cite the author in any work or product based on this material.
- *
- * ===========================================================================
- *
- * Authors: Vladimir Tereshkov
- *
- * File Description:
- * Force tree layout
- */
- #include <ncbi_pch.hpp>
- #include <corelib/ncbistl.hpp>
- #include <gui/opengl/glhelpers.hpp>
- #include <gui/graph/igraph_utils.hpp>
- #include <gui/widgets/phylo_tree/phylo_tree_render.hpp>
- #include <gui/widgets/phylo_tree/phylo_tree_force.hpp>
- #include <FL/Fl.H>
- #include <math.h>
- BEGIN_NCBI_SCOPE
- CPhyloForce::CPhyloForce()
- {
- // default values
- m_SpringLength = 40;
- m_Stiffness = 100;
-
- m_ElectricalRepulsion = 100;
- m_Increment = 0.1;
- m_Initialized = false;
- }
- CPhyloForce::~CPhyloForce()
- {
- }
- void CPhyloForce::x_Layout(CPhyloTreeDataSource& ds)
- {
- bool distMode = m_bDistMode;
- m_bDistMode = false;
- CPhyloRadial::x_Layout(ds);
- m_bDistMode = distMode;
- m_Hash = ds.GetHash();
- Int4 leafs = ds.GetSize();
- Int4 width = ds.GetWidth();
-
- m_xStep = (m_DimX - m_LeftMargin - m_RightMargin) / width;
- m_yStep = (m_DimY - m_TopMargin - m_BottomMargin) / (leafs-1);
-
-
- m_Radius = sqrt(m_xStep*m_xStep + m_yStep*m_yStep)/2;
- m_StartDegree = 0.0;
- m_ParentDegree = 0.0;
- if (ds.GetNormDistance() > 0){
- m_NormDistance = m_ElectricalRepulsion / ds.GetNormDistance();
- }
-
- for (int i=0; i<100; i++) x_Calculate(ds.GetTree());
- // changing raster - x_Calculate for sure changed size in unpredictable way
- TModelRect newRect = ds.GetBoundRect();
-
- m_RasterRect.Init(newRect.Left() - m_RightMargin,
- newRect.Top() - m_TopMargin,
- newRect.Right() + m_RightMargin,
- newRect.Bottom() + m_BottomMargin);
- }
- void CPhyloForce::x_Render(CGlPane& pane, CPhyloTreeDataSource& ds)
- {
- pane.OpenOrtho();
- x_DrawTree( ds.GetTree() );
- pane.Close();
- }
- void CPhyloForce:: x_Calculate(CPhyloTreeNode * node)
- {
- double xForce = 0;
- double yForce = 0;
- double distance;
- double xSpring = 0;
- double ySpring = 0;
- double xRepulsion = 0;
- double yRepulsion = 0;
-
- double adjX;
- double adjY;
- double thisX = node->XY().first;
- double thisY = node->XY().second;
- // two forces calculating at a same time
- for (CPhyloTreeDataSource::TNodeHash::iterator vx=m_Hash.begin(); vx!=m_Hash.end(); vx++){
- CPhyloTreeNode * vertex = vx->second;
- // skip itself
- if (vertex == node) continue;
-
- adjX = vertex->XY().first;
- adjY = vertex->XY().second;
- // repulsion forces calculation
- distance = sqrt((adjX - thisX)*(adjX - thisX) + (adjY - thisY)*(adjY - thisY));
- if( distance == 0 ) distance = 0.0001;
-
- // if (m_bDistMode){
- // m_ElectricalRepulsion = vertex->GetDistance() * m_NormDistance;
- //}
- xRepulsion += ( m_ElectricalRepulsion / distance ) * (( thisX - adjX ) / ( distance ));
- yRepulsion += ( m_ElectricalRepulsion / distance ) * (( thisY - adjY ) / ( distance ));
- // if vertex is adjucent, calculate spring force
- if ((vertex->GetParent() && (vertex->GetParent()->GetValue()==node)) ||
- (node->GetParent() && (node->GetParent()->GetValue()==vertex))){
- xSpring += m_Stiffness * log( distance / m_SpringLength ) * (( thisX - adjX ) / ( distance ));
- ySpring += m_Stiffness * log( distance / m_SpringLength ) * (( thisY - adjY ) / ( distance ));
- }
- }
-
- // resulting force
- xForce = -xSpring + xRepulsion;
- yForce = -ySpring + yRepulsion;
- // altering positions
- node->XY().first += ( xForce * m_Increment );
- node->XY().second += ( yForce * m_Increment );
-
- if (!node->IsLeaf()) {
- for(CPhyloTreeNode::TNodeList_I it = node->SubNodeBegin(); it != node->SubNodeEnd(); it++ ) {
- x_Calculate((*it)->GetValue());
- }
- }
- }
- void CPhyloForce :: x_DrawTree(CPhyloTreeNode * node)
- {
- // label
- if (m_pLabelFont && node->IsLeaf()){
- CGlPoint<int> labelPos(node->GetValue()->XY().first, node->GetValue()->XY().second);
- m_Label.Render(*m_pPane, labelPos, node->GetLabel(), node->GetSelected(), (node->GetAngle() < -1.57 || node->GetAngle()>1.57));
- }
-
- // drawing leaf node
- if (node->GetParent()){
- x_RenderLine(node->GetParent()->GetValue()->XY().first + m_LineWidth, node->GetParent()->GetValue()->XY().second,
- node->GetValue()->XY().first, node->GetValue()->XY().second, m_LineWidth, node->GetSelected()?m_LineSelColor:m_LineColor, node->GetSelected()?m_LineSelHiColor:m_LineHiColor);
- }
- for(CPhyloTreeNode::TNodeList_I it = node->SubNodeBegin(); it != node->SubNodeEnd(); it++ ) x_DrawTree((*it)->GetValue());
- x_RenderNode(node->GetValue()->XY().first, node->GetValue()->XY().second, m_NodeSize, node->GetSelected()?m_NodeSelColor:m_NodeColor);
- }
-
- void CPhyloForce :: x_CountLeafs(CPhyloTreeNode * node, Int4 & lfCount)
- {
- if (node->IsLeaf()) lfCount++;
- for (CPhyloTreeNode::TNodeList_I it = node->SubNodeBegin(); it != node->SubNodeEnd(); it++) x_CountLeafs((*it)->GetValue(), lfCount);
- }
- string CPhyloForce::GetDescription(void)
- {
- return "Force Layout";
- }
- END_NCBI_SCOPE
- /*
- * ===========================================================================
- * $Log: phylo_tree_force.cpp,v $
- * Revision 1000.0 2004/06/01 21:31:04 gouriano
- * PRODUCTION: IMPORTED [GCC34_MSVC7] Dev-tree R1.4
- *
- * Revision 1.4 2004/05/21 22:27:54 gorelenk
- * Added PCH ncbi_pch.hpp
- *
- * Revision 1.3 2004/05/20 15:30:49 tereshko
- * Typo fixed
- *
- * Revision 1.2 2004/05/11 20:53:12 tereshko
- * Work in progress
- *
- * Revision 1.1 2004/05/06 19:41:48 tereshko
- * Initial revision
- *
- * ===========================================================================
- */