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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: phylo_tree_render.cpp,v $
  4.  * PRODUCTION Revision 1000.2  2004/06/02 20:24:36  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.15
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: phylo_tree_render.cpp,v 1000.2 2004/06/02 20:24:36 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.  *
  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 <FL/Fl.H>
  45. #include <math.h>
  46. BEGIN_NCBI_SCOPE
  47. IPhyloTreeRenderer :: IPhyloTreeRenderer()
  48. {
  49.     m_DS        = NULL;
  50.     m_DimX      = GetDimX();
  51.     m_DimY      = GetDimY();
  52.     m_pLabelFont= NULL;
  53.     m_bDistMode = false;
  54.     // raster rect is setup to default hardcoded values
  55.     // it can be changed by Layout()    
  56.     m_RasterRect.Init(0, 0, m_DimX, m_DimY);                      
  57. }
  58. void    IPhyloTreeRenderer::SetHost(IPhyloTreeRendererHost* pHost)
  59. {
  60.     m_pHost = pHost;    
  61. }
  62. void    IPhyloTreeRenderer::x_RenderSelection(CGlPane& pane)
  63. {
  64.      if(m_State == eSelRect) {
  65.         _ASSERT(m_pHost);
  66.         CGlAttrGuard AttrGuard(GL_POLYGON_BIT);
  67.         pane.OpenPixels();
  68.         glLineWidth(1.0f);
  69.         glColor3f(0.0f, 0.0f, 0.0f);
  70.         glLineStipple(1, 0x0F0F);           
  71.         glEnable(GL_LINE_STIPPLE);
  72.         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);        
  73.         glDisable(GL_LINE_SMOOTH);
  74.         
  75.         int x1 = m_StartPoint.X(); 
  76.         int y1 = m_pHost->HMGH_GetVPPosByY(m_StartPoint.Y());
  77.         int x2 = m_DragPoint.X();
  78.         int y2 = m_pHost->HMGH_GetVPPosByY(m_DragPoint.Y());
  79.         if(x2 < x1)
  80.             swap(x1, x2);
  81.         if(y2 < y1)
  82.             swap(y1, y2);
  83.         glBegin(GL_LINES);
  84.             glVertex2d(x1, y2);
  85.             glVertex2d(x2, y2);
  86.             glVertex2d(x2, y2);
  87.             glVertex2d(x2, y1);
  88.             glVertex2d(x1, y2);
  89.             glVertex2d(x1, y1);
  90.         
  91.             glVertex2d(x1, y1);
  92.             glVertex2d(x2, y1);
  93.         glEnd();
  94.         glDisable(GL_LINE_STIPPLE);
  95.         pane.Close();
  96.     }    
  97. }
  98. ////////////////////////////////////////////////////////////////////////////////
  99. /// event handlers
  100. int IPhyloTreeRenderer::x_OnMousePush(CGUIEvent& event)
  101. {    
  102.     CGUIEvent::EGUIState state = event.GetGUIState();
  103.     if((state == CGUIEvent::eSelectState  ||  state == CGUIEvent::eSelectIncState)
  104.         && ((event.GetGUISignal() == CGUIEvent::eSelectSignal) ||(event.GetGUISignal() == CGUIEvent::ePopupSignal)))    {
  105.         if(Fl::event_clicks() == 0) {            
  106.             m_State = eSelPoint;
  107.             m_StartPoint.m_X = Fl::event_x();
  108.             m_StartPoint.m_Y = Fl::event_y();
  109.             m_DragPoint = m_StartPoint;
  110.             bool b_inc = event.GetGUIState() == CGUIEvent::eSelectIncState;
  111.             
  112.             // if not incremental - clear selection
  113.             if (!b_inc) {
  114.                 m_DS->SetSelection(m_DS->GetTree(), false, true);
  115.                 m_SelectedIDs.clear();
  116.             }
  117.             bool b_selected = x_SelectByPoint(m_DS->GetTree());              
  118.             m_State = b_selected ? eSelPoint : eSelRect;
  119.                         
  120.             m_pHost->FireCBEvent();
  121.             m_pHost->HMGH_Redraw();
  122.             x_OnSelectCursor();
  123.         }                
  124.         return 1;
  125.     }
  126.     return 0;
  127. }
  128. int IPhyloTreeRenderer::x_OnMouseDrag(CGUIEvent& event)
  129. {
  130.     CGUIEvent::EGUIState state = event.GetGUIState();
  131.     if(m_State == eSelRect  &&  (state == CGUIEvent::eSelectState
  132.         || state == CGUIEvent::eSelectIncState) )   {
  133.         
  134.         if(Fl::event_x() != m_DragPoint.X()  ||  Fl::event_y() != m_DragPoint.Y())  {
  135.             m_State = eSelRect;
  136.             m_DragPoint.m_X = Fl::event_x();
  137.             m_DragPoint.m_Y = Fl::event_y();
  138.             m_pHost->HMGH_Redraw();
  139.             x_OnSelectCursor();        
  140.         }
  141.     } 
  142.     return 1; // always handle drags
  143. }
  144. int IPhyloTreeRenderer::x_OnMouseRelease(CGUIEvent& event)
  145. {   
  146.     CGUIEvent::EGUIState state = event.GetGUIState();
  147.     if(m_State == eSelPoint)    {
  148.         return 1;
  149.     }
  150.     if(m_State == eSelRect  &&  (state == CGUIEvent::eSelectState
  151.         || state == CGUIEvent::eSelectIncState) 
  152.         &&  ((event.GetGUISignal() == CGUIEvent::eRelease)||(event.GetGUISignal() == CGUIEvent::ePopupSignal)))   {
  153.         
  154.         bool b_inc = event.GetGUIState() == CGUIEvent::eSelectIncState;       
  155.         if (!b_inc) {
  156.             m_DS->SetSelection(m_DS->GetTree(), false, true);
  157.             m_SelectedIDs.clear();
  158.         }
  159.         
  160.         x_SelectByRect(m_DS->GetTree());
  161.         m_pHost->FireCBEvent();
  162.         
  163.         m_State = eIdle;
  164.         m_pHost->HMGH_Redraw();
  165.         x_OnSelectCursor();        
  166.         return 1;
  167.     }
  168.     
  169.     return 0;
  170. }
  171. int IPhyloTreeRenderer::x_OnMouseMove(void)
  172. {
  173.     return (m_State == eIdle) ? 0 : 1;
  174. }
  175. int IPhyloTreeRenderer::x_OnKeyDown(void)
  176. {
  177.     return (m_State == eIdle) ? 0 : 1;
  178. }
  179. int IPhyloTreeRenderer::x_OnKeyUp(void)
  180. {
  181.     return (m_State == eIdle) ? 0 : 1;
  182. }
  183. void IPhyloTreeRenderer::x_OnSelectCursor(void)
  184. {
  185.     switch(m_State)    {
  186.     case eIdle:  m_Cursor = FL_CURSOR_DEFAULT; break;
  187.     case eSelPoint: m_Cursor = FL_CURSOR_DEFAULT; break;
  188.     case eSelRect: m_Cursor = FL_CURSOR_CROSS; break;
  189.     default: break;
  190.     }   
  191.     fl_cursor(m_Cursor, FL_BLACK, FL_WHITE);
  192. }
  193. void IPhyloTreeRenderer::x_RenderLine(double x1, double y1, double x2, double y2, double width, CGlColor color1, CGlColor color2)
  194. {
  195.     glEnable(GL_BLEND);
  196.     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);  
  197.     // correcting line width in x, y directions to not make things look ugly
  198.     double ratio = m_pPane->GetScaleY()/m_pPane->GetScaleX();
  199.         
  200.     // reset line width
  201.     glLineWidth(1.0);        
  202.     glShadeModel(GL_SMOOTH);
  203.     glEnable(GL_LINE_SMOOTH);
  204.     if (width>0){
  205.         // angle
  206.         double angle = (y1==y2)?1.57:atan((x2-x1)/(y1-y2));
  207.         //dx, dy
  208.         double dx = width * cos(angle);
  209.         double dy = width * sin(angle) * ratio;
  210.             
  211.         glBegin(GL_QUADS);    
  212.         // bottom rectangle
  213.         glColor4fv(color1.GetGlColor());    glVertex2d(x1-dx, y1-dy); glVertex2d(x2-dx, y2-dy); 
  214.         glColor4fv(color2.GetGlColor());    glVertex2d(x2, y2); glVertex2d(x1, y1); 
  215.     
  216.         // top rectangle    
  217.         glColor4fv(color2.GetGlColor());  glVertex2d(x1, y1);    glVertex2d(x2, y2); 
  218.         glColor4fv(color1.GetGlColor());  glVertex2d(x2+dx, y2+dy); glVertex2d(x1+dx, y1+dy); 
  219.         glEnd();
  220.         // border    
  221.         glBegin(GL_LINES);        
  222.         glColor4fv(color1.GetGlColor());    
  223.         glVertex2d(x1-dx, y1-dy); glVertex2d(x2-dx, y2-dy);     
  224.         glVertex2d(x2+dx, y2+dy); glVertex2d(x1+dx, y1+dy);
  225.         //glVertex2d(x1-dx, y1-dy); glVertex2d(x2-dx, y2-dy);     
  226.         //glVertex2d(x2+dx, y2+dy); glVertex2d(x1+dx, y1+dy); 
  227.         glEnd();
  228.     }
  229.     else {
  230.         glBegin(GL_LINES);            
  231.         glColor4fv(color1.GetGlColor()); 
  232.         glVertex2d(x1, y1);    
  233.         glVertex2d(x2, y2);         
  234.         glEnd();   
  235.     }
  236.     
  237.   
  238.     glDisable(GL_BLEND);
  239.  
  240. }
  241. void   IPhyloTreeRenderer::x_RenderSpline(double x1, double y1, double x2, double y2)
  242. {
  243.     m_Curve.SetPoint(0, CVect3<float>(x1, y1, 0.0f));
  244.     m_Curve.SetPoint(1, CVect3<float>(x1+10, y1+10, 0.0f));    
  245.     m_Curve.SetPoint(2, CVect3<float>(x1+10, y1+10, 0.0f));    
  246.     m_Curve.SetPoint(3, CVect3<float>(x2, y2, 0.0f));    
  247.     
  248.     m_Curve.Recalc();
  249.     m_Curve.Draw(CGlCurve<CCurveBezier>::eRender_Lines);
  250. }
  251. void IPhyloTreeRenderer::x_RenderNode(double x, double y, double size, CGlColor color)
  252. {
  253.     double ratio = m_pPane->GetScaleY()/m_pPane->GetScaleX();  
  254.     int num_lines = 20;
  255.    
  256.     CGlColor col(color);
  257.     glBegin(GL_TRIANGLE_FAN);    
  258.     for(int i =0;i<num_lines;i++){      
  259.       double angle = i*2*3.14/num_lines; 
  260.       col.Set(col.GetRed()+0.03, col.GetGreen()+0.03, col.GetBlue()+0.03, col.GetAlpha());
  261.       glColor4fv(col.GetGlColor());
  262.       glVertex2f(x+size*cos(angle), y-size*sin(angle)*ratio);      
  263.     }
  264.     glEnd();    
  265. }
  266. CPhyloTreeNode * IPhyloTreeRenderer::x_TestForNode(CPhyloTreeNode * node)
  267. {
  268.     CPhyloTreeNode * selNode = NULL;
  269.     int hit = m_NodeSize * 2;
  270.     int x1  = m_pPane->UnProjectX(m_StartPoint.X())-hit;
  271.     int y1  = m_pPane->UnProjectY(m_pHost->HMGH_GetVPPosByY(m_StartPoint.Y()))+hit;
  272.     int x2  = m_pPane->UnProjectX(m_StartPoint.X())+hit;
  273.     int y2  = m_pPane->UnProjectY(m_pHost->HMGH_GetVPPosByY(m_StartPoint.Y()))-hit;    
  274.     if ((node->XY().first  >= x1 &&  node->XY().first  <=x2)&&
  275.         (node->XY().second >= y2 &&  node->XY().second <=y1)){
  276.         selNode = node;
  277.     }   
  278.         
  279.     if (!node->IsLeaf()) {        
  280.         for(CPhyloTreeNode::TNodeList_I  it = node->SubNodeBegin();  it != node->SubNodeEnd(); it++ )  {            
  281.             if (!selNode) selNode = x_TestForNode((*it)->GetValue());            
  282.         }
  283.     }    
  284.     return selNode;
  285. }
  286. bool IPhyloTreeRenderer::x_SelectByPoint(CPhyloTreeNode * node)
  287. {
  288.     CPhyloTreeNode * selNode = x_TestForNode(node);
  289.     if (selNode) {
  290.         m_DS->SetSelection(selNode, true, true);
  291.         m_SelectedIDs.push_back(selNode->GetID());
  292.     }       
  293.     
  294.     m_Dlist.Invalidate();
  295.     return (selNode!=NULL);
  296. }
  297. bool IPhyloTreeRenderer::x_SelectByRect(CPhyloTreeNode * node)
  298. {
  299.     int x1 = m_pPane->UnProjectX(m_StartPoint.X());
  300.     int y1 = m_pPane->UnProjectY(m_pHost->HMGH_GetVPPosByY(m_StartPoint.Y()));
  301.     int x2 = m_pPane->UnProjectX(m_DragPoint.X());
  302.     int y2 = m_pPane->UnProjectY(m_pHost->HMGH_GetVPPosByY(m_DragPoint.Y()));
  303.     bool bSel = false;
  304.     if (x1 > x2) swap(x1, x2);
  305.     if (y2 > y1) swap(y1, y2);    
  306.     if ((node->XY().first  >= x1 &&  node->XY().first  <=x2)&&
  307.         (node->XY().second >= y2 &&  node->XY().second <=y1)){
  308.         m_DS->SetSelection(node, true, true);
  309.         m_SelectedIDs.push_back(node->GetID());
  310.         bSel = true;        
  311.     }   
  312.         
  313.     if (!node->IsLeaf()) {        
  314.         for(CPhyloTreeNode::TNodeList_I  it = node->SubNodeBegin();  it != node->SubNodeEnd(); it++ )  {                                      
  315.             x_SelectByRect((*it)->GetValue());
  316.         }
  317.     }    
  318.     else if (!bSel){ // check for label, space for improvement here
  319.         CGlPoint<int>   ptNode(node->XY().first, node->XY().second); 
  320.         CGlRect<int>    lblRect = m_Label.GetRect(*m_pPane, ptNode, node->GetLabel(), (node->GetAngle() < -1.57 ||  node->GetAngle()>1.57));
  321.         CGlRect<int>    selRect(x1, y2, x2, y1);
  322.         if (lblRect.Intersects(selRect)){
  323.             m_DS->SetSelection(node, true, true);
  324.             m_SelectedIDs.push_back(node->GetID());
  325.             bSel = true;                
  326.         }
  327.     }
  328.     m_Dlist.Invalidate();
  329.     
  330.     return bSel;
  331. }
  332. int   IPhyloTreeRenderer::handle(CGUIEvent& event, CGlPane& pane)
  333. {    
  334.     m_pPane = &pane;
  335.     int res = 0;
  336.     switch(event.GetFLTKEvent())   {
  337.     case FL_PUSH: res =  x_OnMousePush(event); break;
  338.     case FL_DRAG: res =  x_OnMouseDrag(event); break;
  339.     case FL_RELEASE: res =  x_OnMouseRelease(event); break;
  340.     case FL_MOVE: res =  x_OnMouseMove(); break;
  341.     case FL_KEYDOWN: res =  x_OnKeyDown(); break;
  342.     case FL_KEYUP: res =  x_OnKeyUp(); break;
  343.     }
  344.     //m_pPane = NULL;
  345.     return res;
  346. }
  347. void IPhyloTreeRenderer::Layout(CPhyloTreeDataSource& ds)
  348. {   
  349.     x_Layout(ds);
  350. }
  351. void IPhyloTreeRenderer::Render(CGlPane& pane, CPhyloTreeDataSource& ds)
  352. {    
  353.     m_pPane = &pane;
  354.     m_DS    = &ds;    
  355.     
  356.     /*
  357.     if (m_Dlist.IsValid()) {
  358.         m_Dlist.Call();        
  359.         x_RenderSelection(pane);        
  360.     } else {        
  361.         CGlDisplayListCompile COMPILE(m_Dlist, CGlDisplayList::eCompileAndExecute);            
  362.         x_Render(pane, ds);        
  363.     } 
  364.     */
  365.     x_Render(pane, ds);        
  366.     x_RenderSelection(pane); 
  367. }
  368. bool    IPhyloTreeRenderer::TC_NeedTooltip(int x, int y)
  369. {
  370.     m_StartPoint.m_X = x;  m_StartPoint.m_Y = y;
  371.     return (x_TestForNode(m_DS->GetTree())!=NULL);
  372. }
  373. string  IPhyloTreeRenderer::TC_GetTooltip(int& x, int& y, int& w, int& h)
  374. {
  375.     m_StartPoint.m_X = x;  m_StartPoint.m_Y = y;
  376.     CPhyloTreeNode * hoverNode = x_TestForNode(m_DS->GetTree());    
  377.     
  378.     string ttText = "";
  379.     ttText += ("Node Name: " + (hoverNode->GetLabel().size()?hoverNode->GetLabel():string("No Name")) + "n");
  380.     ttText += ("Distance : " + NStr::DoubleToString(hoverNode->GetDistance()));
  381.     return ttText;
  382. }
  383. void IPhyloTreeRenderer::SetSelectedIDs(const vector<int> & vect)
  384. {    
  385.     m_SelectedIDs.resize(vect.size());
  386.     copy(vect.begin(), vect.end(), m_SelectedIDs.begin());
  387.     m_DS->SetSelection(m_DS->GetTree(), false, true);                
  388.     for (vector<int>::const_iterator it=vect.begin(); it!=vect.end(); it++){
  389.         CPhyloTreeNode * node = m_DS->GetNode(*it);
  390.         if (node)   m_DS->SetSelection(node, true, true);                
  391.     }
  392.     m_pHost->HMGH_Redraw();
  393. }
  394. bool IPhyloTreeRenderer :: IsSelected(CPhyloTreeNode * node)
  395. {
  396.    return (find(m_SelectedIDs.begin(), m_SelectedIDs.end(), node->GetID())!=m_SelectedIDs.end());
  397. }
  398. // default metrics
  399. const double IPhyloTreeRenderer::GetDimX(void) {return 1000.0;}
  400. const double IPhyloTreeRenderer::GetDimY(void) {return 1000.0;}
  401. END_NCBI_SCOPE
  402. /*
  403.  * ===========================================================================
  404.  * $Log: phylo_tree_render.cpp,v $
  405.  * Revision 1000.2  2004/06/02 20:24:36  gouriano
  406.  * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.15
  407.  *
  408.  * Revision 1.15  2004/06/02 16:39:28  tereshko
  409.  * Fixed selections and popup behavior under windows
  410.  *
  411.  * Revision 1.14  2004/05/21 22:27:54  gorelenk
  412.  * Added PCH ncbi_pch.hpp
  413.  *
  414.  * Revision 1.13  2004/05/11 20:53:12  tereshko
  415.  * Work in progress
  416.  *
  417.  * Revision 1.12  2004/05/06 19:42:21  tereshko
  418.  * Rendering improvements
  419.  *
  420.  * Revision 1.11  2004/04/28 19:27:10  tereshko
  421.  * Added support for distances rendering
  422.  *
  423.  * Revision 1.10  2004/04/20 21:57:19  tereshko
  424.  * Major rendering, labeling and performance improvements
  425.  *
  426.  * Revision 1.9  2004/04/14 20:34:00  tereshko
  427.  * Fixed labels truncation
  428.  *
  429.  * Revision 1.8  2004/04/13 20:28:53  tereshko
  430.  * Numerous renderers improvements
  431.  *
  432.  * Revision 1.7  2004/04/01 21:47:25  tereshko
  433.  * Code clean-up
  434.  *
  435.  * Revision 1.6  2004/03/30 17:11:44  tereshko
  436.  * Added support for events broadcasting
  437.  *
  438.  * Revision 1.5  2004/03/03 21:42:06  tereshko
  439.  * Added tooltips support
  440.  *
  441.  * Revision 1.4  2004/03/02 18:29:38  tereshko
  442.  * Added radial tree layout
  443.  *
  444.  * Revision 1.3  2004/02/23 22:52:27  tereshko
  445.  * Rendering Improvements
  446.  *
  447.  * Revision 1.2  2004/02/17 23:44:41  tereshko
  448.  * Changes due to integration into viewer
  449.  *
  450.  * Revision 1.1  2004/02/13 17:05:09  tereshko
  451.  * Phylogenetic Tree Widget initial revision
  452.  *
  453.  * ===========================================================================
  454.  */