phylo_tree_render.cpp
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:16k
- /*
- * ===========================================================================
- * PRODUCTION $Log: phylo_tree_render.cpp,v $
- * PRODUCTION Revision 1000.2 2004/06/02 20:24:36 gouriano
- * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.15
- * PRODUCTION
- * ===========================================================================
- */
- /* $Id: phylo_tree_render.cpp,v 1000.2 2004/06/02 20:24:36 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:
- *
- */
- #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 <FL/Fl.H>
- #include <math.h>
- BEGIN_NCBI_SCOPE
- IPhyloTreeRenderer :: IPhyloTreeRenderer()
- {
- m_DS = NULL;
- m_DimX = GetDimX();
- m_DimY = GetDimY();
- m_pLabelFont= NULL;
- m_bDistMode = false;
- // raster rect is setup to default hardcoded values
- // it can be changed by Layout()
- m_RasterRect.Init(0, 0, m_DimX, m_DimY);
- }
- void IPhyloTreeRenderer::SetHost(IPhyloTreeRendererHost* pHost)
- {
- m_pHost = pHost;
- }
- void IPhyloTreeRenderer::x_RenderSelection(CGlPane& pane)
- {
- if(m_State == eSelRect) {
- _ASSERT(m_pHost);
- CGlAttrGuard AttrGuard(GL_POLYGON_BIT);
- pane.OpenPixels();
- glLineWidth(1.0f);
- glColor3f(0.0f, 0.0f, 0.0f);
- glLineStipple(1, 0x0F0F);
- glEnable(GL_LINE_STIPPLE);
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
- glDisable(GL_LINE_SMOOTH);
-
- int x1 = m_StartPoint.X();
- int y1 = m_pHost->HMGH_GetVPPosByY(m_StartPoint.Y());
- int x2 = m_DragPoint.X();
- int y2 = m_pHost->HMGH_GetVPPosByY(m_DragPoint.Y());
- if(x2 < x1)
- swap(x1, x2);
- if(y2 < y1)
- swap(y1, y2);
- glBegin(GL_LINES);
- glVertex2d(x1, y2);
- glVertex2d(x2, y2);
- glVertex2d(x2, y2);
- glVertex2d(x2, y1);
- glVertex2d(x1, y2);
- glVertex2d(x1, y1);
-
- glVertex2d(x1, y1);
- glVertex2d(x2, y1);
- glEnd();
- glDisable(GL_LINE_STIPPLE);
- pane.Close();
- }
- }
- ////////////////////////////////////////////////////////////////////////////////
- /// event handlers
- int IPhyloTreeRenderer::x_OnMousePush(CGUIEvent& event)
- {
- CGUIEvent::EGUIState state = event.GetGUIState();
- if((state == CGUIEvent::eSelectState || state == CGUIEvent::eSelectIncState)
- && ((event.GetGUISignal() == CGUIEvent::eSelectSignal) ||(event.GetGUISignal() == CGUIEvent::ePopupSignal))) {
- if(Fl::event_clicks() == 0) {
- m_State = eSelPoint;
- m_StartPoint.m_X = Fl::event_x();
- m_StartPoint.m_Y = Fl::event_y();
- m_DragPoint = m_StartPoint;
- bool b_inc = event.GetGUIState() == CGUIEvent::eSelectIncState;
-
- // if not incremental - clear selection
- if (!b_inc) {
- m_DS->SetSelection(m_DS->GetTree(), false, true);
- m_SelectedIDs.clear();
- }
- bool b_selected = x_SelectByPoint(m_DS->GetTree());
- m_State = b_selected ? eSelPoint : eSelRect;
-
- m_pHost->FireCBEvent();
- m_pHost->HMGH_Redraw();
- x_OnSelectCursor();
- }
- return 1;
- }
- return 0;
- }
- int IPhyloTreeRenderer::x_OnMouseDrag(CGUIEvent& event)
- {
- CGUIEvent::EGUIState state = event.GetGUIState();
- if(m_State == eSelRect && (state == CGUIEvent::eSelectState
- || state == CGUIEvent::eSelectIncState) ) {
-
- if(Fl::event_x() != m_DragPoint.X() || Fl::event_y() != m_DragPoint.Y()) {
- m_State = eSelRect;
- m_DragPoint.m_X = Fl::event_x();
- m_DragPoint.m_Y = Fl::event_y();
- m_pHost->HMGH_Redraw();
- x_OnSelectCursor();
- }
- }
- return 1; // always handle drags
- }
- int IPhyloTreeRenderer::x_OnMouseRelease(CGUIEvent& event)
- {
- CGUIEvent::EGUIState state = event.GetGUIState();
- if(m_State == eSelPoint) {
- return 1;
- }
- if(m_State == eSelRect && (state == CGUIEvent::eSelectState
- || state == CGUIEvent::eSelectIncState)
- && ((event.GetGUISignal() == CGUIEvent::eRelease)||(event.GetGUISignal() == CGUIEvent::ePopupSignal))) {
-
- bool b_inc = event.GetGUIState() == CGUIEvent::eSelectIncState;
- if (!b_inc) {
- m_DS->SetSelection(m_DS->GetTree(), false, true);
- m_SelectedIDs.clear();
- }
-
- x_SelectByRect(m_DS->GetTree());
- m_pHost->FireCBEvent();
-
- m_State = eIdle;
- m_pHost->HMGH_Redraw();
- x_OnSelectCursor();
- return 1;
- }
-
- return 0;
- }
- int IPhyloTreeRenderer::x_OnMouseMove(void)
- {
- return (m_State == eIdle) ? 0 : 1;
- }
- int IPhyloTreeRenderer::x_OnKeyDown(void)
- {
- return (m_State == eIdle) ? 0 : 1;
- }
- int IPhyloTreeRenderer::x_OnKeyUp(void)
- {
- return (m_State == eIdle) ? 0 : 1;
- }
- void IPhyloTreeRenderer::x_OnSelectCursor(void)
- {
- switch(m_State) {
- case eIdle: m_Cursor = FL_CURSOR_DEFAULT; break;
- case eSelPoint: m_Cursor = FL_CURSOR_DEFAULT; break;
- case eSelRect: m_Cursor = FL_CURSOR_CROSS; break;
- default: break;
- }
- fl_cursor(m_Cursor, FL_BLACK, FL_WHITE);
- }
- void IPhyloTreeRenderer::x_RenderLine(double x1, double y1, double x2, double y2, double width, CGlColor color1, CGlColor color2)
- {
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- // correcting line width in x, y directions to not make things look ugly
- double ratio = m_pPane->GetScaleY()/m_pPane->GetScaleX();
-
- // reset line width
- glLineWidth(1.0);
- glShadeModel(GL_SMOOTH);
- glEnable(GL_LINE_SMOOTH);
- if (width>0){
- // angle
- double angle = (y1==y2)?1.57:atan((x2-x1)/(y1-y2));
- //dx, dy
- double dx = width * cos(angle);
- double dy = width * sin(angle) * ratio;
-
- glBegin(GL_QUADS);
- // bottom rectangle
- glColor4fv(color1.GetGlColor()); glVertex2d(x1-dx, y1-dy); glVertex2d(x2-dx, y2-dy);
- glColor4fv(color2.GetGlColor()); glVertex2d(x2, y2); glVertex2d(x1, y1);
-
- // top rectangle
- glColor4fv(color2.GetGlColor()); glVertex2d(x1, y1); glVertex2d(x2, y2);
- glColor4fv(color1.GetGlColor()); glVertex2d(x2+dx, y2+dy); glVertex2d(x1+dx, y1+dy);
- glEnd();
- // border
- glBegin(GL_LINES);
- glColor4fv(color1.GetGlColor());
- glVertex2d(x1-dx, y1-dy); glVertex2d(x2-dx, y2-dy);
- glVertex2d(x2+dx, y2+dy); glVertex2d(x1+dx, y1+dy);
- //glVertex2d(x1-dx, y1-dy); glVertex2d(x2-dx, y2-dy);
- //glVertex2d(x2+dx, y2+dy); glVertex2d(x1+dx, y1+dy);
- glEnd();
- }
- else {
- glBegin(GL_LINES);
- glColor4fv(color1.GetGlColor());
- glVertex2d(x1, y1);
- glVertex2d(x2, y2);
- glEnd();
- }
-
-
- glDisable(GL_BLEND);
-
- }
- void IPhyloTreeRenderer::x_RenderSpline(double x1, double y1, double x2, double y2)
- {
- m_Curve.SetPoint(0, CVect3<float>(x1, y1, 0.0f));
- m_Curve.SetPoint(1, CVect3<float>(x1+10, y1+10, 0.0f));
- m_Curve.SetPoint(2, CVect3<float>(x1+10, y1+10, 0.0f));
- m_Curve.SetPoint(3, CVect3<float>(x2, y2, 0.0f));
-
- m_Curve.Recalc();
- m_Curve.Draw(CGlCurve<CCurveBezier>::eRender_Lines);
- }
- void IPhyloTreeRenderer::x_RenderNode(double x, double y, double size, CGlColor color)
- {
- double ratio = m_pPane->GetScaleY()/m_pPane->GetScaleX();
- int num_lines = 20;
-
- CGlColor col(color);
- glBegin(GL_TRIANGLE_FAN);
- for(int i =0;i<num_lines;i++){
- double angle = i*2*3.14/num_lines;
- col.Set(col.GetRed()+0.03, col.GetGreen()+0.03, col.GetBlue()+0.03, col.GetAlpha());
- glColor4fv(col.GetGlColor());
- glVertex2f(x+size*cos(angle), y-size*sin(angle)*ratio);
- }
- glEnd();
- }
- CPhyloTreeNode * IPhyloTreeRenderer::x_TestForNode(CPhyloTreeNode * node)
- {
- CPhyloTreeNode * selNode = NULL;
- int hit = m_NodeSize * 2;
- int x1 = m_pPane->UnProjectX(m_StartPoint.X())-hit;
- int y1 = m_pPane->UnProjectY(m_pHost->HMGH_GetVPPosByY(m_StartPoint.Y()))+hit;
- int x2 = m_pPane->UnProjectX(m_StartPoint.X())+hit;
- int y2 = m_pPane->UnProjectY(m_pHost->HMGH_GetVPPosByY(m_StartPoint.Y()))-hit;
- if ((node->XY().first >= x1 && node->XY().first <=x2)&&
- (node->XY().second >= y2 && node->XY().second <=y1)){
- selNode = node;
- }
-
- if (!node->IsLeaf()) {
- for(CPhyloTreeNode::TNodeList_I it = node->SubNodeBegin(); it != node->SubNodeEnd(); it++ ) {
- if (!selNode) selNode = x_TestForNode((*it)->GetValue());
- }
- }
- return selNode;
- }
- bool IPhyloTreeRenderer::x_SelectByPoint(CPhyloTreeNode * node)
- {
- CPhyloTreeNode * selNode = x_TestForNode(node);
- if (selNode) {
- m_DS->SetSelection(selNode, true, true);
- m_SelectedIDs.push_back(selNode->GetID());
- }
-
- m_Dlist.Invalidate();
- return (selNode!=NULL);
- }
- bool IPhyloTreeRenderer::x_SelectByRect(CPhyloTreeNode * node)
- {
- int x1 = m_pPane->UnProjectX(m_StartPoint.X());
- int y1 = m_pPane->UnProjectY(m_pHost->HMGH_GetVPPosByY(m_StartPoint.Y()));
- int x2 = m_pPane->UnProjectX(m_DragPoint.X());
- int y2 = m_pPane->UnProjectY(m_pHost->HMGH_GetVPPosByY(m_DragPoint.Y()));
- bool bSel = false;
- if (x1 > x2) swap(x1, x2);
- if (y2 > y1) swap(y1, y2);
- if ((node->XY().first >= x1 && node->XY().first <=x2)&&
- (node->XY().second >= y2 && node->XY().second <=y1)){
- m_DS->SetSelection(node, true, true);
- m_SelectedIDs.push_back(node->GetID());
- bSel = true;
- }
-
- if (!node->IsLeaf()) {
- for(CPhyloTreeNode::TNodeList_I it = node->SubNodeBegin(); it != node->SubNodeEnd(); it++ ) {
- x_SelectByRect((*it)->GetValue());
- }
- }
- else if (!bSel){ // check for label, space for improvement here
- CGlPoint<int> ptNode(node->XY().first, node->XY().second);
- CGlRect<int> lblRect = m_Label.GetRect(*m_pPane, ptNode, node->GetLabel(), (node->GetAngle() < -1.57 || node->GetAngle()>1.57));
- CGlRect<int> selRect(x1, y2, x2, y1);
- if (lblRect.Intersects(selRect)){
- m_DS->SetSelection(node, true, true);
- m_SelectedIDs.push_back(node->GetID());
- bSel = true;
- }
- }
- m_Dlist.Invalidate();
-
- return bSel;
- }
- int IPhyloTreeRenderer::handle(CGUIEvent& event, CGlPane& pane)
- {
- m_pPane = &pane;
- int res = 0;
- switch(event.GetFLTKEvent()) {
- case FL_PUSH: res = x_OnMousePush(event); break;
- case FL_DRAG: res = x_OnMouseDrag(event); break;
- case FL_RELEASE: res = x_OnMouseRelease(event); break;
- case FL_MOVE: res = x_OnMouseMove(); break;
- case FL_KEYDOWN: res = x_OnKeyDown(); break;
- case FL_KEYUP: res = x_OnKeyUp(); break;
- }
- //m_pPane = NULL;
- return res;
- }
- void IPhyloTreeRenderer::Layout(CPhyloTreeDataSource& ds)
- {
- x_Layout(ds);
- }
- void IPhyloTreeRenderer::Render(CGlPane& pane, CPhyloTreeDataSource& ds)
- {
- m_pPane = &pane;
- m_DS = &ds;
-
- /*
- if (m_Dlist.IsValid()) {
- m_Dlist.Call();
- x_RenderSelection(pane);
- } else {
- CGlDisplayListCompile COMPILE(m_Dlist, CGlDisplayList::eCompileAndExecute);
- x_Render(pane, ds);
- }
- */
- x_Render(pane, ds);
- x_RenderSelection(pane);
- }
- bool IPhyloTreeRenderer::TC_NeedTooltip(int x, int y)
- {
- m_StartPoint.m_X = x; m_StartPoint.m_Y = y;
- return (x_TestForNode(m_DS->GetTree())!=NULL);
- }
- string IPhyloTreeRenderer::TC_GetTooltip(int& x, int& y, int& w, int& h)
- {
- m_StartPoint.m_X = x; m_StartPoint.m_Y = y;
- CPhyloTreeNode * hoverNode = x_TestForNode(m_DS->GetTree());
-
- string ttText = "";
- ttText += ("Node Name: " + (hoverNode->GetLabel().size()?hoverNode->GetLabel():string("No Name")) + "n");
- ttText += ("Distance : " + NStr::DoubleToString(hoverNode->GetDistance()));
- return ttText;
- }
- void IPhyloTreeRenderer::SetSelectedIDs(const vector<int> & vect)
- {
- m_SelectedIDs.resize(vect.size());
- copy(vect.begin(), vect.end(), m_SelectedIDs.begin());
- m_DS->SetSelection(m_DS->GetTree(), false, true);
- for (vector<int>::const_iterator it=vect.begin(); it!=vect.end(); it++){
- CPhyloTreeNode * node = m_DS->GetNode(*it);
- if (node) m_DS->SetSelection(node, true, true);
- }
- m_pHost->HMGH_Redraw();
- }
- bool IPhyloTreeRenderer :: IsSelected(CPhyloTreeNode * node)
- {
- return (find(m_SelectedIDs.begin(), m_SelectedIDs.end(), node->GetID())!=m_SelectedIDs.end());
- }
- // default metrics
- const double IPhyloTreeRenderer::GetDimX(void) {return 1000.0;}
- const double IPhyloTreeRenderer::GetDimY(void) {return 1000.0;}
- END_NCBI_SCOPE
- /*
- * ===========================================================================
- * $Log: phylo_tree_render.cpp,v $
- * Revision 1000.2 2004/06/02 20:24:36 gouriano
- * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.15
- *
- * Revision 1.15 2004/06/02 16:39:28 tereshko
- * Fixed selections and popup behavior under windows
- *
- * Revision 1.14 2004/05/21 22:27:54 gorelenk
- * Added PCH ncbi_pch.hpp
- *
- * Revision 1.13 2004/05/11 20:53:12 tereshko
- * Work in progress
- *
- * Revision 1.12 2004/05/06 19:42:21 tereshko
- * Rendering improvements
- *
- * Revision 1.11 2004/04/28 19:27:10 tereshko
- * Added support for distances rendering
- *
- * Revision 1.10 2004/04/20 21:57:19 tereshko
- * Major rendering, labeling and performance improvements
- *
- * Revision 1.9 2004/04/14 20:34:00 tereshko
- * Fixed labels truncation
- *
- * Revision 1.8 2004/04/13 20:28:53 tereshko
- * Numerous renderers improvements
- *
- * Revision 1.7 2004/04/01 21:47:25 tereshko
- * Code clean-up
- *
- * Revision 1.6 2004/03/30 17:11:44 tereshko
- * Added support for events broadcasting
- *
- * Revision 1.5 2004/03/03 21:42:06 tereshko
- * Added tooltips support
- *
- * Revision 1.4 2004/03/02 18:29:38 tereshko
- * Added radial tree layout
- *
- * Revision 1.3 2004/02/23 22:52:27 tereshko
- * Rendering Improvements
- *
- * Revision 1.2 2004/02/17 23:44:41 tereshko
- * Changes due to integration into viewer
- *
- * Revision 1.1 2004/02/13 17:05:09 tereshko
- * Phylogenetic Tree Widget initial revision
- *
- * ===========================================================================
- */