NCBI C++ ToolKit
tree_graphics_model.cpp
Go to the documentation of this file.

Go to the SVN repository for this file.

1 /* $Id: tree_graphics_model.cpp 47292 2022-12-21 00:32:34Z evgeniev $
2  * ===========================================================================
3  *
4  * PUBLIC DOMAIN NOTICE
5  * National Center for Biotechnology Information
6  *
7  * This software/database is a "United States Government Work" under the
8  * terms of the United States Copyright Act. It was written as part of
9  * the author's official duties as a United States Government employee and
10  * thus cannot be copyrighted. This software/database is freely available
11  * to the public for use. The National Library of Medicine and the U.S.
12  * Government have not placed any restriction on its use or reproduction.
13  *
14  * Although all reasonable efforts have been taken to ensure the accuracy
15  * and reliability of the software and data, the NLM and the U.S.
16  * Government do not and cannot warrant the performance or results that
17  * may be obtained by using this software or data. The NLM and the U.S.
18  * Government disclaim all warranties, express or implied, including
19  * warranties of performance, merchantability or fitness for any particular
20  * purpose.
21  *
22  * Please cite the author in any work or product based on this material.
23  *
24  * ===========================================================================
25  *
26  * Authors: Bob Falk
27  *
28  * File Description:
29  *
30  */
31 
32 #include <ncbi_pch.hpp>
33 #include <corelib/ncbistl.hpp>
34 
41 
42 
43 #include <gui/opengl/glresmgr.hpp>
44 
45 #include <gui/print/pdf.hpp>
47 #include <gui/print/pdf_object.hpp>
48 
50 
51 #include <gui/utils/matrix3.hpp>
52 #include <gui/utils/matrix4.hpp>
53 
54 #include <corelib/ncbitime.hpp>
55 
56 #include <cmath>
57 
59 
60 
62 {
63  if (!IsVisible())
64  return;
65 
66  CVect2<float> scale((float)m_State->GetScaleFactor().X(),
67  (float)m_State->GetScaleFactor().Y());
68 
69  for (size_t i=0; i<m_BoundaryNodes.size(); ++i) {
70  CPhyloTreeNode& node = (*m_Tree)[m_BoundaryNodes[i]];
71 
72  if ((*node).GetDisplayChildren() == CPhyloNodeData::eHideChildren)
73  continue;
74 
75  float alpha_mod = 1.0f;
76 
77  if ((*node).GetSelectedState()!=CPhyloNodeData::eSelected) {
78  if (m_SL->GetSelectionVisibility() ==
80  alpha_mod = m_SL->GetNonSelectedAlpha();
81  }
82  }
83 
84  (*node).GetSubtreeBoundary()->RenderBoundaryVbo(scale, alpha_mod, m_IncludeLabels);
85 
86  if ((*node).GetSubtreeBoundary()->Overlaps(m_Pane.GetVisibleRect())) {
87  (*node).GetSubtreeBoundary()->RenderVbo();
88  }
89  }
90 }
91 
93 {
94  if (!IsVisible())
95  return;
96 
97  for (size_t i=0; i<m_BoundaryNodes.size(); ++i) {
98  CPhyloTreeNode& node = (*m_Tree)[m_BoundaryNodes[i]];
99 
100  if ((*node).GetDisplayChildren() == CPhyloNodeData::eHideChildren)
101  continue;
102 
103  //glTranslated((**n).X(), (**n).Y(), 0.0);
104  float alpha_mod = 1.0f;
105 
106  if ((*node).GetSelectedState() != CPhyloNodeData::eSelected) {
107  if (m_SL->GetSelectionVisibility() ==
109  alpha_mod = m_SL->GetNonSelectedAlpha();
110  }
111  }
112 
113  CVect2<float> scale2d((float)m_State->GetScaleFactor().X(),
114  (float)m_State->GetScaleFactor().Y());
115 
116  (*node).GetSubtreeBoundary()->RenderBoundaryVbo(scale2d, alpha_mod);
117 
118  pdf->PrintTriBuffer((*node).GetSubtreeBoundary()->GetBoundaryTris(), m_Pane.GetViewport());
119 
120  CRef<CGlVboNode> boundaryEdges = node->GetSubtreeBoundary()->GetBoundaryEdges();
121  if (boundaryEdges && boundaryEdges->GetVertexFormat() == IVboGeom::kVertexFormatVertex2D)
122  pdf->PrintLineBuffer((*node).GetSubtreeBoundary()->GetBoundaryEdges(), m_Pane.GetViewport());
123  }
124 }
125 
126 void CTreeTriFanNode::CreateVbo(size_t numSements)
127 {
128  m_VBOGeom.Reset(CGlResMgr::Instance().CreateTreeNodeVboGeom(numSements));
129 }
130 
132 : m_BoundaryNode(NULL)
133 , m_TriFanNode(NULL)
134 , m_Tree(NULL)
135 , m_RotateLabels(false)
136 , m_RenderPdfTooltips(false)
137 , m_RenderTime(0.0f)
138 , m_LineRenderTime(0.0f)
139 , m_NodesRenderTime(0.0f)
140 , m_BoundaryRenderTime(0.0f)
141 , m_NodeRenderCount(0)
142 {
143 #ifdef ATTRIB_MENU_SUPPORT
145  CAttribMenu* sub_menu = m.AddSubMenuUnique("Model", this);
146 
147  sub_menu->AddFloatReadOnly("Render Time", &m_RenderTime);
148  sub_menu->AddFloatReadOnly("Line Render Time", &m_LineRenderTime);
149  sub_menu->AddFloatReadOnly("Nodes Render Time", &m_NodesRenderTime);
150  sub_menu->AddFloatReadOnly("Boundary Render Time", &m_BoundaryRenderTime);
151  sub_menu->AddIntReadOnly("Nodes Render Count", &m_NodeRenderCount);
152  sub_menu->AddFloatReadOnly("Total Time", &m_TotalTime);
153  sub_menu->AddFloatReadOnly("Collision Update Time", &m_CDUpdateTime);
154 #endif
155 }
156 
158 {
159  delete m_BoundaryNode;
161 
162  delete m_TriFanNode;
163  m_TriFanNode = NULL;
164 
165 #ifdef ATTRIB_MENU_SUPPORT
167 #endif
168 }
169 
170 
172 {
173  m_Tree = t;
174  m_ColorTable.Reset(t->GetColorTable());
175 
176  // Order that the CGlVboNode's are created is significant, as it
177  // determines their drawing order (and thus what is drawn on top of what)
178 
179  CGlVboNode* filler_points_node = FindGeomNode("FillerPoints");
180  if (!filler_points_node) {
181  filler_points_node = AddGeomNode("FillerPoints", true);
182  filler_points_node->GetState().Enable(GL_BLEND);
183  filler_points_node->GetState().BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
184  filler_points_node->GetState().Disable(GL_TEXTURE_2D);
185  filler_points_node->GetState().Disable(GL_TEXTURE_1D);
186  filler_points_node->GetState().ColorC(CRgbaColor(1.0f, 1.0f, 1.0f, 1.0f));
187 
188  // Don't draw points in pdf mode (pdf fills line elbows differently)
189  filler_points_node->SkipTarget(eRenderPDF, true);
190 
191  // off by default. only used in rectangular pseudo-spline layout
192  filler_points_node->SetVisible(false);
193  }
194 
195  CGlVboNode* sel_filler_points_node = FindGeomNode("SelectedFillerPoints");
196  if (!sel_filler_points_node) {
197  sel_filler_points_node = AddGeomNode("SelectedFillerPoints", true);
198  sel_filler_points_node->GetState().Enable(GL_BLEND);
199  sel_filler_points_node->GetState().BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
200  sel_filler_points_node->GetState().Disable(GL_TEXTURE_2D);
201  sel_filler_points_node->GetState().Disable(GL_TEXTURE_1D);
202  sel_filler_points_node->GetState().ColorC(CRgbaColor(1.0f, 1.0f, 1.0f, 1.0f));
203 
204  // Don't draw points in pdf mode (pdf fills line elbows differently)
205  sel_filler_points_node->SkipTarget(eRenderPDF, true);
206 
207  // off by default. only used in rectangular pseudo-spline layout
208  sel_filler_points_node->SetVisible(false);
209  }
210 
211  CGlVboNode* edge_node = FindGeomNode("TreeEdges");
212  if (!edge_node) {
213  edge_node = AddGeomNode(GL_LINES, "TreeEdges", true);
214  edge_node->GetState().Disable(GL_TEXTURE_2D);
215  edge_node->GetState().Disable(GL_TEXTURE_1D);
218  edge_node->GetState().ColorC(CRgbaColor(1.0f, 1.0f, 1.0f, 1.0f));
219  }
220 
221  CGlVboNode* boundary_node = FindGeomNode("BoundaryNodes");
222  if (!boundary_node) {
223  boundary_node = AddGeomNode(GL_TRIANGLES, "BoundaryNodes", true);
224  boundary_node->GetState().Disable(GL_BLEND);
225  boundary_node->GetState().Disable(GL_TEXTURE_2D);
226  boundary_node->GetState().Disable(GL_TEXTURE_1D);
227  }
228 
229  // These edges are inside wider edges (same geometry buffer as 'TreeEdges')
230  CGlVboNode* narrow_edge_node = FindGeomNode("NarrowTreeEdges");
231  if (!narrow_edge_node) {
232  narrow_edge_node = AddGeomNode("NarrowTreeEdges", true);
233  narrow_edge_node->SetVBOGeom(CGlResMgr::Instance().CreateNarrowTreeEdgeVboGeom(edge_node->GetVBOGeom()));
234 
235  narrow_edge_node->GetState().LineWidth(1.0f);
236  // color to be used for lighting in blending equation
237  narrow_edge_node->GetState().ColorC(CRgbaColor(1.0f, 1.0f, 1.0f, 0.7f));
238  narrow_edge_node->GetState().Disable(GL_TEXTURE_2D);
239  narrow_edge_node->GetState().Disable(GL_TEXTURE_1D);
240  narrow_edge_node->GetState().LineJoinStyle(CGlState::eMiteredJoin);
241  narrow_edge_node->GetState().LineCapStyle(CGlState::eButtCap);
242  }
243 
244  // We draw selected edges last so they are always on top of other edges.
245  // This is easiest to do if we put them in their own vbo. This is only
246  // needed for distance-based rendering though since edges should never
247  // overlap if layout has full control of spacing
248  CGlVboNode* sel_edge_node = FindGeomNode("SelectedTreeEdges");
249  if (!sel_edge_node) {
250  sel_edge_node = AddGeomNode(GL_LINES, "SelectedTreeEdges", true);
251  sel_edge_node->GetState().Disable(GL_TEXTURE_2D);
252  sel_edge_node->GetState().Disable(GL_TEXTURE_1D);
254  sel_edge_node->GetState().LineCapStyle(CGlState::eRoundCap);
255  sel_edge_node->GetState().ColorC(CRgbaColor(1.0f, 1.0f, 1.0f, 1.0f));
256  }
257 
258  // Narrow edges for selected edges (when using distance-based rendering)
259  CGlVboNode* sel_narrow_edge_node = FindGeomNode("SelectedNarrowTreeEdges");
260  if (!sel_narrow_edge_node) {
261  sel_narrow_edge_node = AddGeomNode("SelectedNarrowTreeEdges", true);
262  sel_narrow_edge_node->SetVBOGeom(CGlResMgr::Instance().CreateNarrowTreeEdgeVboGeom(sel_edge_node->GetVBOGeom()));
263 
264  sel_narrow_edge_node->GetState().LineWidth(1.0f);
265  // color to be used for lighting in blending equation
266  sel_narrow_edge_node->GetState().ColorC(CRgbaColor(1.0f, 1.0f, 1.0f, 0.7f));
267  sel_narrow_edge_node->GetState().Disable(GL_TEXTURE_2D);
268  sel_narrow_edge_node->GetState().Disable(GL_TEXTURE_1D);
269  sel_narrow_edge_node->GetState().LineJoinStyle(CGlState::eMiteredJoin);
270  sel_narrow_edge_node->GetState().LineCapStyle(CGlState::eButtCap);
271  }
272 
273  // Used by some renderings to fill in joint where two lines with
274  // width > 1 meet (otherwise you get a gap at the corner,as shown
275  // below where two lines of width 3 pixels meet but leave the position
276  // marked by ? blank.
277  // ?xxxxxxx
278  // xxxxxxxx <- line 2
279  // xxxxxxxx
280  // xxx
281  // xxx <-line 1
282  // xxx
283  // (faster):
284  // Draw the edge buffer twice, but second time call it a
285  // point buffer and set the offset to only draw the corner points
286  // (preferably without using an index buffer. (Can't draw end points
287  // since that would extend the line)
288  if (filler_points_node != NULL) {
289  filler_points_node->SetVBOGeom(CGlResMgr::Instance().CreateFillerPointVboGeom(edge_node->GetVBOGeom()));
290  filler_points_node->GetState().Disable(GL_TEXTURE_1D);
291  filler_points_node->GetState().Disable(GL_TEXTURE_2D);
292  }
293 
294  if (sel_filler_points_node != NULL) {
295  sel_filler_points_node->SetVBOGeom(CGlResMgr::Instance().CreateFillerPointVboGeom(sel_edge_node->GetVBOGeom()));
296  sel_filler_points_node->GetState().Disable(GL_TEXTURE_1D);
297  sel_filler_points_node->GetState().Disable(GL_TEXTURE_2D);
298  }
299 
300  CGlVboNode* point_node = FindGeomNode("NodePoints");
301  if (!point_node) {
302  point_node = AddGeomNode(GL_POINTS, "NodePoints", true);
303  point_node->GetState().Enable(GL_TEXTURE_1D);
304  point_node->GetState().Disable(GL_TEXTURE_2D);
305  point_node->GetState().ColorC(CRgbaColor(1.0f, 1.0f, 1.0f, 1.0f));
306  point_node->GetState().PointSize(1.0f);
307  }
308 
309  if (m_BoundaryNode == NULL) {
311  if (m_SL.GetPointerOrNull() != NULL)
313  m_BoundaryNode->GetState().Disable(GL_TEXTURE_1D);
314  m_BoundaryNode->GetState().Disable(GL_TEXTURE_2D);
315  }
316 
317  if (m_TriFanNode == NULL) {
319  m_TriFanNode->GetState().Disable(GL_TEXTURE_2D);
320  m_TriFanNode->GetState().Disable(GL_TEXTURE_1D);
321  m_TriFanNode->GetState().Disable(GL_BLEND);
322  m_TriFanNode->GetState().ShadeModel(GL_SMOOTH);
323  m_TriFanNode->GetState().PolygonMode(GL_FRONT_AND_BACK, GL_FILL);
324  }
325 }
326 
328 {
329  if (!m_CollapseTexture) {
330  CGlAttrGuard guard(GL_ALL_ATTRIB_BITS);
331 
332  CIRef<I3DFrameBuffer> tmp_framebuffer(CGlResMgr::Instance().CreateFrameBuffer(512));
333 
334  tmp_framebuffer->SetTextureFiltering(GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR);
335  tmp_framebuffer->SetClearColor(0, 0, 0, 0);
336  tmp_framebuffer->CreateFrameBuffer();
337 
338  if (tmp_framebuffer->IsValid()) {
339  auto renderer = [&vb]() {
340  IRender& gl = GetGl();
341 
342  gl.Viewport(0, 0, 512, 512);
343 
344  GLdouble saveMVMatrix[16], saveProjMatrix[16];
345  gl.GetModelViewMatrix(saveMVMatrix);
346  gl.GetProjectionMatrix(saveProjMatrix);
347 
348  gl.MatrixMode(GL_MODELVIEW);
349  gl.LoadIdentity();
350 
351  gl.MatrixMode(GL_PROJECTION);
352  gl.LoadIdentity();
353  gl.Ortho(0.0, 1.0, -0.5, 0.5, -1.0, 1.0);
354 
355  gl.Disable(GL_BLEND);
356  gl.Disable(GL_TEXTURE_2D);
357  gl.Disable(GL_TEXTURE_1D);
358  gl.PolygonMode(GL_FRONT_AND_BACK, GL_FILL);
359 
360  gl.Color4f(1.0f, 1.0f, 1.0f, 1.0f);
361 
362  gl.Begin(GL_TRIANGLE_STRIP);
363  for (const auto& v : vb)
364  gl.Vertex3f(v.X(), v.Y(), 0.0f);
365  gl.End();
366 
367  gl.MatrixMode(GL_PROJECTION);
368  gl.LoadMatrixd(saveProjMatrix);
369 
370  gl.MatrixMode(GL_MODELVIEW);
371  gl.LoadMatrixd(saveMVMatrix);
372  };
373 
374  tmp_framebuffer->Render(renderer);
375  tmp_framebuffer->GenerateMipMaps();
376 
377  // Set rendering target back
378  m_CollapseTexture.Reset(tmp_framebuffer->Get3DTexture());
379  m_CollapseTexture->SetTexEnv(GL_MODULATE);
380  m_CollapseTexture->SetFilterMag(GL_LINEAR);
381  m_CollapseTexture->SetFilterMin(GL_LINEAR_MIPMAP_LINEAR);
382  m_CollapseTexture->SetParams();
383  tmp_framebuffer->ReleaseTexture();
384  }
385  }
386 
387  if (!m_CollapseTexture)
388  return nullptr;
389 
390  CIRef<IVboGeom> geom_node = FindGeomObject("collapsed_tex");
391  if (!geom_node) {
392  geom_node = AddGeomObject(GL_TRIANGLE_STRIP, "collapsed_tex");
393 
394  vector<CVect2<float> > vb;
395 
396  vb.push_back(CVect2<float>(0.0f, -0.5f));
397  vb.push_back(CVect2<float>(1.0f, -0.5f));
398  vb.push_back(CVect2<float>(0.0f, 0.5f));
399  vb.push_back(CVect2<float>(1.0f, 0.5f));
400 
401  geom_node->SetVertexBuffer2D(vb);
402 
403  vector<CVect2<float> > tb;
404  tb.push_back(CVect2<float>(0.0f, 0.0f));
405  tb.push_back(CVect2<float>(1.0f, 0.0f));
406  tb.push_back(CVect2<float>(0.0f, 1.0f));
407  tb.push_back(CVect2<float>(1.0f, 1.0f));
408 
409  geom_node->SetTexCoordBuffer(tb);
410  }
411 
412  // Since PDF has anti-aliasing built-in, we skip it for all but the most opaque node
413  CGlVboNode* n = AddTempGeomNode("CollapsedNode", true);
414  n->SetVBOGeom(geom_node);
415 
416  n->GetState().BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
417  n->GetState().Disable(GL_LIGHTING);
418  n->GetState().Enable(GL_BLEND);
419  n->GetState().Enable(GL_TEXTURE_2D);
420  n->GetState().Disable(GL_TEXTURE_1D);
421  n->GetState().SetTexture(m_CollapseTexture.GetNCPointer());
422  n->GetState().ScaleInvarient(true);
423 
424  return n;
425 }
426 
428 {
429  // Make sure color class is right size (nobody has added virtual functions
430  // or other data).
431  _ASSERT(sizeof(CRgbaColor) == 16);
432 
433  CGlVboNode* point_node = FindGeomNode("NodePoints");
434  CGlVboNode* filler_point_node = FindGeomNode("FillerPoints");
435  CGlVboNode* sel_filler_point_node = FindGeomNode("SelectedFillerPoints");
436  CGlVboNode* edge_node = FindGeomNode("TreeEdges");
437  CGlVboNode* narrow_edge_node = FindGeomNode("NarrowTreeEdges");
438  CGlVboNode* sel_edge_node = FindGeomNode("SelectedTreeEdges");
439  CGlVboNode* sel_narrow_edge_node = FindGeomNode("SelectedNarrowTreeEdges");
440 
441 
442  if (m_NodeIndices.size() > 0) {
443  point_node->GetState().SetTexture(m_ColorTable->GetTexture());
444 
445  point_node->SetVisible(true);
446  // Gets cleared in clear arrays. Seems like a bit of a hack...
447  point_node->SetDefaultPosition();
448 
449  vector<CVect2<float> > coords;
450  coords.reserve(m_NodeIndices.size());
451 
452  for (size_t i=0; i<m_NodeIndices.size(); ++i) {
453  CPhyloTreeNode& n = (*m_Tree)[m_NodeIndices[i]];
454  if (n->GetDisplayChildren() != CPhyloNodeData::eHideChildren)
455  coords.push_back(n->XY());
456  }
457 
458  point_node->SetVertexBuffer2D(coords);
459  }
460  else if (point_node != NULL) {
461  point_node->SetVisible(false);
462  }
463 
464  if (edge_node != NULL) {
465  size_t vb_size = edge_node->GetVertexCount();
466 
467  if (vb_size > 0) {
468  // The filler points are set to visible only for pseudo-spline (right-angle
469  // edges) rendering. Otherwise visible will be set to false.
470  if (filler_point_node->IsVisible())
471  filler_point_node->SetDefaultPosition();
472 
473  edge_node->SetVisible(true);
474  // Gets cleared in clear arrays
475  edge_node->SetDefaultPosition();
476 
477  if (narrow_edge_node != NULL) {
478  narrow_edge_node->SetDefaultPosition();
479  }
480  }
481  else {
482  edge_node->SetVisible(false);
483  }
484 
485  // Selected edges are in their own buffer so they can be drawn after (and show up on top of)
486  // non-selected edges
487  vb_size = sel_edge_node->GetVertexCount();
488 
489  if (vb_size > 0) {
490  // The filler points are set to visible only for pseudo-spline (right-angle
491  // edges) rendering. Otherwise visible will be set to false.
492  if (sel_filler_point_node->IsVisible())
493  sel_filler_point_node->SetDefaultPosition();
494 
495  sel_edge_node->SetVisible(true);
496  // Gets cleared in clear arrays
497  sel_edge_node->SetDefaultPosition();
498 
499  if (sel_narrow_edge_node != NULL) {
500  sel_narrow_edge_node->SetDefaultPosition();
501  }
502  }
503  else {
504  sel_edge_node->SetVisible(false);
505  }
506  }
507 }
508 
510 {
512 
513  m_NodeIndices.clear();
514 
515  if (m_BoundaryNode != NULL)
517 
518  if (m_TriFanNode != NULL)
520 
521  CGlVboNode* edge_node = FindGeomNode("TreeEdges");
522  if (edge_node)
523  edge_node->SetVertexBuffer2D(vector<CVect2<float> >());
524 
525  CGlVboNode* sel_edge_node = FindGeomNode("SelectedTreeEdges");
526  if (sel_edge_node)
527  sel_edge_node->SetVertexBuffer2D(vector<CVect2<float> >());
528 
529  // Default this to false before re-creating buffers, so that only the circular
530  // layout has to call EnableCircularLabelTrimming()
532 }
533 
535 {
537  m_CladogramCenter = cladogram_center;
538  // Magic number pi/32.0 is gap left in circular layout so that top and bottom do not blend together.
539  m_DeltaTheta = (float(M_PI*2.0 - M_PI / 32.0)) / float(m_Tree->GetRoot().GetValue().GetNumLeavesEx());
540 }
541 
543 {
544  m_SL.Reset(&sl);
546 
547  if (m_BoundaryNode != NULL)
549 }
550 
552  const CVect3<float>& scale,
553  CPhyloTreeNode &n,
554  bool truncate_labels)
555 {
556  float a1 = n->GetAngle();
557  float a2;
558 
559  // Get expected angle of leaf next leaf node on the perimiter that is closer
560  // to the centerline (y=0)
561  if (a1 <= float(M_PI / 2.0) || a1 > float(3.0*M_PI / 2.0))
562  a2 = a1 - m_DeltaTheta;
563  else
564  a2 = a1 + m_DeltaTheta;
565 
566  // Angle saved in nodes assume square viewport. This scales angle to match
567  // current (possibly non-square) viewport
568  a1 = n->GetScaledAngle(scale, a1, false);
569  a2 = n->GetScaledAngle(scale, a2, false);
570 
571  TVPPoint p1 = pane.Project(n->X(), n->Y());
573 
574  // This does not give correct result ... (maybe warp the angle the way we
575  // do in node class?)
576  float r = CVect2<float>(p1.X() - p2.X(), p1.Y() - p2.Y()).Length();
577 
578  // Normally node labels are set to 'not visible' when they overlap. We
579  // disable that here since we compute overlap based on position around the circle
580  n->SetVisible(true);
581  // compute vertical distance between nodes:
582  float vdist = std::abs(r*sin(a1) - r*sin(a2));
583  if (vdist < m_SL->GetFont().TextHeight()) {
584  // Compute horizontal distance between nodes. Since labels should not overlap the nodes
585  // themselves, we also subtract out the node radius * 2 here, and subtract 2 pixels to
586  // guarantee some minimal spacing between labels and adjancent nodes
587  float hdist = std::abs(r*cos(a1) - r*cos(a2)) - (2.0f*n->GetNodeDisplaySize() + 2.0f);
588  if (hdist > 0.0f)
589  n->Render(pane, m_SL->GetFont(), m_ColorTable.GetPointer(), scale, truncate_labels, (TModelUnit)hdist);
590  }
591  else {
592  n->Render(pane, m_SL->GetFont(), m_ColorTable.GetPointer(), scale, truncate_labels);
593  }
594 }
595 
597  const CVect3<float>& scale,
598  const CPhyloTreeNode &n,
599  bool& visible) const
600 {
601 
602  // Angle of node around circle (0..2*pi)
603  float a1 = n->GetAngle();
604  float a2;
605 
606  visible = true;
607 
608  // Wherever a1 is around circle (0..2pi) we re-map it to the equivalent
609  // angle in the first quadrant (0..pi/2) to make our calculations consistent.
610  // Since our goal is to find the rotation amount for the label, for some
611  // quadrants we will reverse that rotation (via reverse_rotation).
612  float reverse_rotation = 1.0f;
613  if (a1 > float(M_PI / 2.0)) {
614  if (a1 < float(M_PI)) {
615  a1 = float(M_PI) - a1;
616  reverse_rotation = -1.0f;
617  }
618  else if (a1 < float(3.0*M_PI / 2.0)) {
619  a1 = a1 - float(M_PI);
620  }
621  else {
622  a1 = float(2.0*M_PI) - a1;
623  reverse_rotation = -1.0f;
624  }
625  }
626 
627  // a2 is the presumed angle of the leaf node that is closest to 'n'
628  // on the side closer to the zero-angle. m_DeltaTheta was computed
629  // during layout of the view. We use this as a proxy for the adjacent
630  // node, which we do not have here.
631  a2 = a1 - m_DeltaTheta;
632 
633  // distance from the center of the circular cladogram to current node:
634  float r = (n->XY() - m_CladogramCenter).Length();
635 
636  // Get horizontal and vertical distance from current to adjacent
637  // node in screen coordinates
638  float vdist = r*sin(a1) - r*sin(a2);
639  float hdist = r*cos(a2) - r*cos(a1);
640  vdist /= scale.Y(); // Dividing by scale gives distance in pixels
641  hdist /= scale.X();
642 
643  // Get maximum text height (include descender) + some extra (1.0)
644  // to keep rotated labels from overlapping
647 
648  TModelUnit th_2 = th / 2.0;
649 
650  // Length of collapsed nodes can extend up to 4*m_SL->GetMaxNodeSize()
651  // see: CPhyloNodeData::GetNodeWidthScaler
652  TModelUnit adjacent_offset = std::max(th, 4.0*m_SL->GetMaxNodeSize());
653  TModelUnit adjacent_offset2 = adjacent_offset / 2.0;
654 
655  // Get positions of the current node and the expected location of the
656  // adjacent node in screen (pixel) coordinates
657  TVPPoint p1 = pane.Project(n->X(), n->Y());
658  CVect2<float> current_node_lower_left_label_pos(p1.X(), p1.Y() - th_2);
659  CVect2<float> adjacent_node_pos(p1.X() + hdist, p1.Y() - vdist);
660 
661  // This is the offset from the adjacent node position to the position
662  // on the sphere centered on the adjacent node at 3*pi/4:
663  CVect2<float> u2_offset(cos(3.0*M_PI / 4.0), sin(3.0*M_PI / 4.0));
664  u2_offset *= adjacent_offset2;
665 
666  float required_angle = 0.0f;
667 
668  // When horizontal distance is very small between the nodes, we
669  // artificially increase since adjacent node Has to be to the right
670  // of the current node by the radius of the circle (which is based on
671  // text height) to work. (And this makes the transition from non-rotated
672  // to rotated smoother)
673  if (hdist < th) {
674  u2_offset.X() += (th / 2.0)*(th - hdist) / th; // hdist 0..th_2 => th_2/2 .. 0.0
675  }
676 
677  // Get vector from lower left corner of this node's label to the point on a
678  // circle around the adjacent node at 3pi/4 (halfway from 90 and 180 degrees)
679  CVect2<float> circle_pos(adjacent_node_pos + u2_offset);
680  CVect2<float> v = circle_pos - current_node_lower_left_label_pos;
681 
682  // If nodes are far enough apart in vertical direction that text will
683  // not overlap, the vector from the circle position to the lower-left
684  // label position of our node will be negative (and we won't do anything)
685  if (v.Y() > 0.0f) {
686  // Convert vector to world (from screen) coordinates
687  v.X() *= scale.X();
688  v.Y() *= scale.Y();
689  v.Normalize();
690 
691  // Skip label if nodes are so close that text will overlap no matter
692  // what. This is for cases where viewing area is too narrow in X. If
693  // too narrow in Y, we hide all labels
694  if ((CVect2<float>(p1.X(), p1.Y()) - adjacent_node_pos).Length() < th_2) {
695  visible = false;
696  return 0.0f;
697  }
698 
699  // Dot product of the vectors is the cosine of the angle between them.
700  // Since the lower edge of our text box vector is (1,0), the
701  // dot product (v.dot(1,0)) is v.X()
702  float dp = v.X();
703  required_angle = acos(dp); // inverse cos to get angle
704 
705  // Don't let angle be > than angle to center of cladogram. sometimes when nodes
706  // are alomost on top of each other, angle will be too large.
707  if (required_angle > a1)
708  required_angle = a1;
709 
710  // reverse rotation if needed to match correct quadrant
711  required_angle *= reverse_rotation;
712  }
713 
714  return required_angle;
715 }
716 
717 
719  const CVect3<float>& scale,
720  CPhyloTreeNode &n,
721  bool truncate_labels)
722 {
723  // Normally node labels are set to 'not visible' when they overlap. Disable
724  // that here since we compute overlap based on position around the circle
725  n->SetVisible(true);
726 
727  bool visible;
728  float required_angle = x_CircularLabelMinAngle(pane, scale, n, visible);
729 
730  if (visible) {
731  // Render the node. Update the angle to the computed value first (then undo that)
732  float a = n->GetAngle();
733  n->SetAngle(required_angle);
734  n->RenderRotated(pane, m_SL->GetFont(), m_ColorTable.GetPointer(), scale, a, truncate_labels);
735  n->SetAngle(a);
736  }
737 }
738 
739 
741  const CPhyloTreeNode& node,
742  bool& visible) const
743 {
744  if (!m_RotateLabels) {
745  return 0.0f;
746  }
747  else {
748  if (m_EnableCircularLabelTrimming && node.IsLeafEx()) {
749  CVect3<float> scale(pane.GetScaleX(), pane.GetScaleY(), 1.0f);
750  return x_CircularLabelMinAngle(pane, scale, node, visible);
751  }
752  else {
753  return node->GetAngle();
754  }
755  }
756 }
757 
759  const CVect3<float>& scale)
760 {
761  /// Visibility for the node is based on visibility of the geometry (triangle fan)
762  /// not the associated label, but it would look strange to have the label (which
763  /// is larger than the node) without the node.
764  if (!m_TriFanNode->IsVisible())
765  return;
766 
767  // Indices in the datastructure for lower-left and upper right corners of
768  // current rectangle
771 
772  m_NodeRenderCount = 0;
773 
774  CMatrix4<float> mat;
775  mat.Identity();
776 
777  // Set flag for all nodes in visible area that they have not been drawn
778  // yet. Must do this since node labels are alpha-blended and so look
779  // different if they are drawn multiple tims.
780  for (int x = posi_ll.X(); x <= posi_ur.X(); ++x) {
781  for (int y = posi_ll.Y(); y <= posi_ur.Y(); ++y) {
783 
784  // Should always be true unless vis rectangle not intialized
785  if (!m_CollisionData.InBounds(idx))
786  continue;
787 
788  std::vector<size_t>& cell_nodes = m_CollisionData.Get(idx).m_Labels;
789 
790  // Flag each node in this cell as not drawn
791  for (size_t i=0; i<cell_nodes.size(); ++i) {
792  (*m_Tree)[cell_nodes[i]]->SetAlreadyDrawn(false);
793  }
794  }
795  }
796 
797  bool truncate_labels = (m_SL->GetLabelTruncation() ==
799 
800  // Iterate over the currently-visible grid which subdivides
801  // the space occupied by the tree into individual cells
802  for (int x = posi_ll.X(); x <= posi_ur.X(); ++x) {
803  for (int y = posi_ll.Y(); y <= posi_ur.Y(); ++y) {
805 
806  // Should always be true unless vis rectangle not intialized
807  if (!m_CollisionData.InBounds(idx))
808  continue;
809 
810  std::vector<size_t>& cell_nodes = m_CollisionData.Get(idx).m_Labels;
811 
812  // Find collisions between nodes hashed in this entry
813  for (size_t i=0; i<cell_nodes.size(); ++i) {
814  // Label draw checks visibility (updated in UpdateVisibility)
815 
816  CPhyloTreeNode &n = (*m_Tree)[cell_nodes[i]];
817 
818 
820  if (!n->GetAlreadyDrawn()) {
821  if (!m_RotateLabels) {
822  if (m_EnableCircularLabelTrimming && n.IsLeafEx()) {
823  x_CircularLabelTrim(pane, scale, n, truncate_labels);
824  }
825  else {
826  n->Render(pane, m_SL->GetFont(), m_ColorTable.GetPointer(), scale, truncate_labels);
827  }
828  }
829  else {
830  if (m_EnableCircularLabelTrimming && n.IsLeafEx()) {
831  x_CircularLabelMinRotate(pane, scale, n, truncate_labels);
832  }
833  else {
834  n->RenderRotated(pane, m_SL->GetFont(), m_ColorTable.GetPointer(), scale, n->GetAngle(), truncate_labels);
835  }
836  }
837  n->SetAlreadyDrawn(true);
838  }
839  }
841 
842  bool vis = false;
843  vis = (n->GetDisplayChildren() != CPhyloNodeData::eHideChildren) &&
844  !n->HasNodeMarker();
845 
846  if (vis) {
847  mat[3] = n->X(); // mat[3] = mat(0,3)
848  mat[7] = n->Y(); // mat[7] = mat(1,3)
849 
850  mat[0] = n->GetNodeDisplaySize(); // mat[0] == mat(0,0)
851  mat[5] = n->GetNodeDisplaySize(); // mat[5] == mat(1,1)
852 
853  CRgbaColor c = n->GetNodeDisplayColor();
856  m_TriFanNode->Render();
857  }
858  }
859  }
860  }
861 }
862 
864 {
865  CStopWatch render_total;
866  render_total.Start();
867 
868  CVect3<float> scale(pane.GetScaleX(), pane.GetScaleY(), 1.0f);
869 
870  pane.OpenOrtho();
872 
873  IRender& gl = GetGl();
874 
875  // Don't want to combine texture with color. Why does glcolor matter if
876  // mode is decal?
877  glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
878  CRgbaColor c(1.0f, 1.0f, 1.0f, 1.0f);
879  glColorC(c);
880 
881  CStopWatch t;
882  t.Start();
883 
884  if (m_BoundaryNode != NULL) {
886  m_BoundaryNode->SetPane(pane);
889  }
890 
891  m_BoundaryRenderTime = t.Restart();
892 
893  // Set as not visible any CGlVboNode objects that render marker nodes
894  // if nodes in general are not visible.
895  for (size_t i=0; i<m_TempGeomNodes.size(); ++i) {
896  if (m_TempGeomNodes[i]->GetName() == "MarkerNode") {
897  m_TempGeomNodes[i]->SetVisible(m_TriFanNode->IsVisible());
898  }
899  }
900 
901  CGlModel2D::Render(pane);
902 
903  m_LineRenderTime = (float)t.Restart();
904 
905  if (m_TriFanNode != NULL) {
906  x_RenderNodes(pane, scale);
907  }
908 
909  m_NodesRenderTime = (float)t.Restart();
910 
911  m_RenderTime = render_total.Elapsed();
912 
914  pane.Close();
915 
916  // other views don't concern themselves with textures
917  // so make sure these are disabled before returning
918  gl.Disable(GL_TEXTURE_1D);
919  gl.Disable(GL_TEXTURE_2D);
920 }
921 
923  CRef<CPdf>& pdf,
924  CVect3<float> scale)
925 {
927  return;
928 
929  // This is only in case we want tooltips in the pdf file
931  label.SetScheme(m_SL.GetObject(), m_Tree);
932 
933  IRender& gl = GetGl();
934 
935  bool truncate_labels = (m_SL->GetLabelTruncation() ==
937 
938  // Not easy to clip rotated labels
939  if (GetRotateLabels())
940  truncate_labels = false;
941 
942  float uu_inv = 1.0f/pdf->GetOptions().GetUserUnit();
943  scale *= uu_inv;
944 
945  // Do all backgrounds first since they are separate objects (in pdf)
946  // and we're putting all the text into a single object.
947  size_t i;
948  gl.Enable(GL_BLEND);
949  for (i=0; i<m_NodeIndices.size(); ++i) {
950  CPhyloTreeNode& n = (*m_Tree)[m_NodeIndices[i]];
951 
952  if (!n->GetAlreadyDrawn() && n->GetVisible()) {
953  string txt;
954  CVect2<float> pos = n->GetTextOut(pane, m_SL->GetFont(), scale, truncate_labels, txt);
955 
956  gl.LoadIdentity();
957  if (n->GetLabelBgColorIdx() != -1 && txt.length() > 0) {
958  CRgbaColor c = m_ColorTable->GetColor((int)n->GetLabelBgColorIdx());
959  gl.Color4fv((GLfloat*)c.GetColorArray());
960 
961  // There seems to be some kind of off-by-one error in here in that I have to specify
962  // - pane.GetScaleX/Y() to get the correct position. And in the rotated case this works
963  // but not up until the largest (zoomed in until uu_inv is very small) images.
964  if (!m_RotateLabels) {
966  TModelUnit text_w = gl.TextWidth(&(m_SL->GetFont()), txt.c_str());
967 
968  gl.PolygonMode(GL_FRONT_AND_BACK, GL_FILL);
969  gl.RectC(TModelRect(pos.X() - pane.GetScaleX(),
970  pos.Y() - pane.GetScaleY(),
971  pos.X() + (text_w + 1.0) * pane.GetScaleX()*double(uu_inv) - pane.GetScaleX(),
972  pos.Y() + (text_h + 1.0) * pane.GetScaleY()*double(uu_inv) - pane.GetScaleY()));
973 
974  }
975  else {
976  float angle;
977  CVect4<CVect2<float> > corners = n->GetRotatedTextBox(scale, angle);
978  gl.Begin(GL_TRIANGLE_STRIP);
979  gl.Vertex2f(corners[3].X() - pane.GetScaleX(), corners[3].Y() - pane.GetScaleY());
980  gl.Vertex2f(corners[0].X() - pane.GetScaleX(), corners[0].Y() - pane.GetScaleY());
981  gl.Vertex2f(corners[2].X() - pane.GetScaleX(), corners[2].Y() - pane.GetScaleY());
982  gl.Vertex2f(corners[1].X() - pane.GetScaleX(), corners[1].Y() - pane.GetScaleY());
983  gl.End();
984  }
985  }
986  }
987  }
988 
989 
990  // Now print out all the text
992 
993  for (i=0; i<m_NodeIndices.size(); ++i) {
994  CPhyloTreeNode &n = (*m_Tree)[m_NodeIndices[i]];
995 
996  if (!n->GetAlreadyDrawn()) {
997  if (n->GetVisible()) {
998  string txt;
999  CVect2<float> pos;
1000  CVect2<float> posp;
1001  double px, py;
1002  double dummyz;
1003 
1005  float font_size = (float)m_SL->GetFont().GetFontSize();
1006 
1007  CRgbaColor c = n->GetTextDisplayColor();
1008 
1009  if (!m_RotateLabels) {
1010  pos = n->GetTextOut(pane, m_SL->GetFont(), scale, truncate_labels, txt);
1011 
1012  CGlRect<float> r = n->GetLabelRect();
1013 
1014  pos.X() = (float)(n->XY().X());
1015  pos.Y() = (float)(n->XY().Y());
1016 
1017  gluProjectX(pos.X(), pos.Y(), 0.0,
1019  &px, &py, &dummyz);
1020  posp.X() = px + r.Left()*uu_inv;
1021  posp.Y() = py + r.Bottom()*uu_inv;
1022 
1023  pdf->PrintText(pdf->GetFontHandler(), face, font_size, posp,
1024  txt.c_str(), c);
1025  }
1026  else {
1027  float a;
1028  pos = n->GetRotatedTextPos(scale, a);
1029  float cos_a = cosf(a);
1030  float sin_a = sinf(a);
1031 
1032  gluProjectX(pos.X(), pos.Y(), 0.0,
1034  &px, &py, &dummyz);
1035  posp.X() = px;
1036  posp.Y() = py;
1037 
1038  // Matrix for transforming text - rotates around the point posp. Matrix is
1039  // given in column major order (so sin_a/-sin_a are switched)
1040  CMatrix3<double> m(cos_a, -sin_a, posp.X(), sin_a, cos_a, posp.Y(), 0.0f, 0.0f, 1.0f);
1041 
1042  pdf->PrintText(pdf->GetFontHandler(), face, font_size, m,
1043  n->GetDisplayLabel().c_str(), c);
1044  }
1045  }
1046 
1047 
1048  if (m_RenderPdfTooltips) {
1049  std::string final_text = label.GetToolTipForNode(
1050  *m_Tree, n, m_SL->SetTooltipFormat(), "\n");
1051  CVect2<float> lower_left;
1052  CVect2<float> upper_right;
1053  n->GetBoundingRect(CVect2<float>(scale.X(), scale.Y()), lower_left, upper_right, m_RotateLabels);
1054  if (final_text.length() == 0) {
1055  lower_left -= 2.0f;
1056  upper_right += 2.0f;
1057  }
1058  else {
1059  lower_left.Y() += 3.0f;
1060  upper_right.Y() -= 3.0f;
1061  }
1062  CVect4<float> bound(lower_left.X(), lower_left.Y(), upper_right.X(), upper_right.Y());
1063 
1064  // These tips use javascript alert boxes (less attractive...)
1065  //pdf->AddJSTooltip(pane, final_text, n->GetDisplayLabel(), bound);
1066  pdf->AddTooltip(pane, final_text, bound);
1067  }
1068 
1069  n->SetAlreadyDrawn(true);
1070  }
1071  }
1072  pdf->EndContent();
1073 }
1074 
1076 {
1077  double px, py;
1078  double dummyz;
1079 
1080  gluProjectX(p.X(), p.Y(), 0.0,
1082  &px, &py, &dummyz);
1083 
1084  return CVect2<float>((float)px, (float)py);
1085 }
1086 
1087 
1089  CRef<CPdf>& pdf,
1090  CVect3<float> scale)
1091 {
1092  if (!m_TriFanNode->IsVisible())
1093  return;
1094 
1095  map<int, string> shader_ids;
1096 
1097  // For rendering to the screen, I do not use a color buffer since there are only two colors
1098  // (I use a blending trick instead). Here create the needed color buffer for pdf rendering.
1099  vector<CRgbaColor> colors, prev_colors;
1100 
1101  m_TriFanNode->GetColorBuffer(prev_colors);
1102 
1103  CRgbaColor cback(1.0f, 1.0f, 1.0f);
1104  float uu_inv = 1.0f/pdf->GetOptions().GetUserUnit();
1105  scale *= uu_inv;
1106 
1107  IRender& gl = GetGl();
1108 
1109  // for each node, check its color and see if we have already drawn a node
1110  // of the same color to the pdf file. If so, just add a new shader
1111  // reference to the existing pdf triangle shader with an appropriate
1112  // transformation. If not, create a new pdf shader and add it to the
1113  // shading dictionary.
1114  for (size_t i=0; i<m_NodeIndices.size(); ++i) {
1115  CPhyloTreeNode& n = (*m_Tree)[m_NodeIndices[i]];
1116 
1117  bool vis = false;
1118  vis = (n->GetDisplayChildren() != CPhyloNodeData::eHideChildren) &&
1119  !n->HasNodeMarker();
1120 
1121  if (vis) {
1122  // create a unique identifer (unsigned int) for the color
1123  CRgbaColor c = n->GetNodeDisplayColor();
1124 
1125  unsigned int id = c.GetRedUC()<<16;
1126  id |= c.GetGreenUC()<<8;
1127  id |= c.GetBlueUC();
1128 
1129  // see if we've already created a node of this color
1130  string shader = shader_ids[id];
1131 
1132  // If not, create a new triangle shader node and map its identifer
1133  // to the colors unique id value
1134  if (shader == "") {
1135  // Fill color buffer before calling pdf to render tris:
1136  colors.clear();
1137  colors.resize(prev_colors.size(), c);
1138  colors[0] = cback;
1140 
1141  //shader = pdf->AddShadedTris(m_TriFanNode);
1142  shader = pdf->AddShadedTris(m_TriFanNode, pane.GetViewport(),
1143  CPdfObject::e16Bit, m_ColorTable.GetPointer(), -200, 200, -200, 200);
1144 
1145  shader_ids[id] = shader;
1146  }
1147 
1148  // Pdf render function gets transformation values from opengl
1149  CMatrix3<double> mat;
1150  mat.Identity();
1151 
1152  gl.MatrixMode(GL_MODELVIEW);
1153  gl.PushMatrix();
1154 
1155  gl.Translatef(n->X(), n->Y(), 0.0f);
1156 
1157  gl.Scalef(n->GetNodeDisplaySize() * scale.X(), n->GetNodeDisplaySize() * scale.Y(), 1.0f);
1158 
1159  // create a reference in the pdf file to the shader (tris) at the nodes position
1160  pdf->RenderShaderInstance(m_TriFanNode, shader, pane.GetViewport());
1161  gl.PopMatrix();
1162  }
1163  }
1164 
1165  // Restore previous colors for node (so that it will work correctly
1166  // in non-pdf drawing)
1167  m_TriFanNode->SetColorBuffer(prev_colors);
1168 }
1169 
1171 {
1172  pane.OpenOrtho();
1173 
1174  // get viewport directly from pane since size may exceed
1175  // opengl max viewport size (but not max pdf viewable page size)
1176  //glGetIntegerv(GL_VIEWPORT, m_Viewport);
1177  m_Viewport[0] = pane.GetViewport().Left();
1178  m_Viewport[1] = pane.GetViewport().Bottom();
1179  m_Viewport[2] = pane.GetViewport().Width();
1180  m_Viewport[3] = pane.GetViewport().Height();
1181 
1182  IRender& gl = GetGl();
1185 
1186  CVect3<float> scale((float)pane.GetScaleX(), (float)pane.GetScaleY(), 1.0f);
1187 
1188  if (m_BoundaryNode != NULL) {
1190  m_BoundaryNode->SetPane(pane);
1192  m_BoundaryNode->RenderPdf(pdf);
1193  }
1194 
1195  // Set as not visible any CGlVboNode objects that render marker nodes
1196  // if nodes in general are not visible.
1197  for (size_t i = 0; i<m_TempGeomNodes.size(); ++i) {
1198  if (m_TempGeomNodes[i]->GetName() == "MarkerNode")
1199  m_TempGeomNodes[i]->SetVisible(m_TriFanNode->IsVisible());
1200  }
1201 
1202  pdf->PrintModel(pane, *this, m_ColorTable.GetPointer());
1203  x_RenderNodesPdf(pane, pdf, scale);
1204  x_RenderNodeLabelsPdf(pane, pdf, scale);
1205 
1206  pane.Close();
1207 }
1208 
1209 
static CAttribMenu & GetInstance()
Return a static instance of CAttribMenu.
Definition: attrib_menu.cpp:50
class CAttribMenuItem
CAttribIntMenuItem * AddIntReadOnly(const std::string &name, int *user_value)
CAttribMenu * AddSubMenuUnique(const std::string &name, void *user_value=NULL)
Convienance function to add a submenu to this menu.
CAttribFloatMenuItem * AddFloatReadOnly(const std::string &name, float *user_value)
Add entries to the menu which display the users value but do not update it.
bool RemoveMenuR(const std::string &name, void *user_value=NULL)
Search the menu(s) recursively for menu 'name' with the specified user data 'user_value'.
CGlAttrGuard - guard class for restoring OpenGL attributes.
Definition: glutils.hpp:130
class CGlPane
Definition: glpane.hpp:62
CGlVboNode A rendering node that holds a vertex buffer object.
Definition: glvbonode.hpp:64
@ ePdfText
Definition: pdf.hpp:64
void AddTooltip(CGlPane &pane, const string &txt, CVect4< float > &rect)
Definition: pdf.cpp:307
void RenderShaderInstance(CGlVboNode *node, const string &shader_id, const TVPRect &vp)
Display an instance of a set of shaded triangles "shader_id", which is returned by AddShadedTris.
Definition: pdf.cpp:1244
CRef< CPdfFontHandler > GetFontHandler()
Definition: pdf.hpp:95
void PrintModel(CGlPane &pane, CGlModel2D &model, CRgbaGradColorTable *color_table=NULL)
Print contents of (2D) model.
Definition: pdf.cpp:269
void PrintTriBuffer(CGlVboNode *node, const TVPRect &vp, CRgbaGradColorTable *color_table=NULL)
Prints AddShadedTris and RenderShaderInstance to save an instance of shaded triangles to the pdf.
Definition: pdf.cpp:1304
string AddShadedTris(CGlVboNode *node, const TVPRect &vp, CRgbaGradColorTable *color_table, CPdfObject::EBitCount bit_count=CPdfObject::e16Bit)
Add a triangle buffer to the pdf (but do not display it) Returns the ID of the triangle shader object...
Definition: pdf.cpp:1109
virtual void EndContent()
Definition: pdf.cpp:174
void PrintLineBuffer(CGlVboNode *node, const TVPRect &vp, CRgbaGradColorTable *color_table=NULL)
Prints the lines in buffer "node" to the pdf using current graphics state, modelview and projection m...
Definition: pdf.cpp:618
void PrintText(CRef< CPdfFontHandler > font_handler, EFontFace face, float font_size, CVect2< float > &p, const char *txt, const CRgbaColor &c)
Write a string of text at the specified position (in screen coords).
Definition: pdf.cpp:219
virtual TPdfObjectRef BeginContent(EContentType t)
Definition: pdf.cpp:167
int GetNumLeavesEx() const
bool IsLeafEx() const
Return true if node is a leaf or is collapsed.
string & SetTooltipFormat(void)
GLdouble GetMaxNodeSize() const
size range for variable-sized collapsed nodes (so min node size here may be greater than node size)
TLabelTruncation & GetLabelTruncation()
TSelectionVisibility GetSelectionVisibility() const
float GetNonSelectedAlpha() const
const CGlTextureFont & GetFont(void) const
Tree subclass also has functions and data needed for rendering and selection.
Definition: phylo_tree.hpp:52
TPdfUnit GetUserUnit() const
class CRgbaColor provides a simple abstraction for managing colors.
Definition: rgba_color.hpp:58
TVeci GetMaxVisIndex() const
TVeci GetMinVisIndex() const
Get min/max visible indices for grid (as per UpdateVisibility)
TElemType & Get(const TVeci &item)
bool InBounds(const TVeci &item) const
Return true if the index falls within the current table.
CStopWatch –.
Definition: ncbitime.hpp:1938
class CTreeBoundaryNode
virtual void x_Render()
Does actual rendering work.
void SetPane(const CGlPane &p)
vector< size_t > m_BoundaryNodes
Vector of all nodes that have a boundary defined.
CRef< CPhyloTreeScheme > m_SL
void RenderPdf(CRef< CPdf > &pdf)
void SetIncludeLabels(bool b)
void SetScheme(CPhyloTreeScheme &sl)
void SetScheme(CPhyloTreeScheme &sl)
Set rendering scheme for tree (has info needed for node sizes)
CGlVboNode * AddTempCollapsedNode(const vector< CVect2< float > > &vb)
Return a node that can be used to represent a collapsed tree.
CRef< CPhyloTreeScheme > m_SL
void x_RenderNodesPdf(CGlPane &pane, CRef< CPdf > &pdf, CVect3< float > scale)
CRef< CRgbaGradColorTable > m_ColorTable
CIRef< I3DTexture > m_CollapseTexture
void EnableCircularLabelTrimming(const CVect2< float > &cladogram_center)
Called for circular layout - enables trimming of non-rotated labels based on proximity to adjacent le...
CTreeBoundaryNode * m_BoundaryNode
virtual void RenderPDF(CGlPane &pane, CRef< CPdf > &pdf)
Draw to PDF file.
void Init(CPhyloTree *t)
Allocate any default buffers etc.
void SetScheme(CPhyloTreeScheme &sl)
Set rendering scheme for tree (some nodes need this to render)
float x_CircularLabelMinAngle(const CGlPane &pane, const CVect3< float > &scale, const CPhyloTreeNode &n, bool &visible) const
virtual void Render(CGlPane &pane)
Draw all the nodes.
virtual void ClearArrays()
Clear arrays prior to re-synching with the model.
CTreeCollisionModel2D m_CollisionData
void x_RenderNodes(CGlPane &pane, const CVect3< float > &scale)
void x_RenderNodeLabelsPdf(CGlPane &pane, CRef< CPdf > &pdf, CVect3< float > scale)
CVect2< float > x_Project(CVect2< float > &p)
bool m_EnableCircularLabelTrimming
These are specialized for rendering circular cladograms.
void x_CircularLabelMinRotate(const CGlPane &pane, const CVect3< float > &scale, CPhyloTreeNode &n, bool truncate_labels)
CTreeTriFanNode * m_TriFanNode
virtual void SyncBuffers()
Update buffers as needed.
float GetCurrentRotationAngle(const CGlPane &pane, const CPhyloTreeNode &n, bool &visible) const
Return node's label rotation angle for current zoom level.
void x_CircularLabelTrim(const CGlPane &pane, const CVect3< float > &scale, CPhyloTreeNode &n, bool truncate_labels)
CVect2< float > m_CladogramCenter
vector< size_t > m_NodeIndices
TData & GetValue()
Return the value object for the node.
Definition: tree_model.hpp:159
TNodeType & GetRoot()
Return a reference to the root node of the tree.
Definition: tree_model.hpp:254
class CTreeTriFanNode
void CreateVbo(size_t numSements)
bool GetLabelVisibility() const
Definition: vect4.hpp:49
virtual CPrintOptions & GetOptions()
static const Colors colors
Definition: cn3d_colors.cpp:50
#define false
Definition: bool.h:36
string
Definition: cgiapp.hpp:687
#define NULL
Definition: ncbistd.hpp:225
void Identity()
Definition: matrix3.hpp:313
float Length() const
Definition: vect2.hpp:271
T & X()
Definition: vect3.hpp:110
T & X()
Definition: vect2.hpp:107
T & Y()
Definition: vect3.hpp:112
void Identity()
Definition: matrix4.hpp:373
void Normalize()
Definition: vect2.hpp:296
T & Y()
Definition: vect4.hpp:113
T & Y()
Definition: vect2.hpp:109
CIRef< IVboGeom > AddGeomObject(GLenum node_type, const string &name)
Add a geometry (vertex buffer object) node.
Definition: glmodel2d.cpp:222
void ClearPositions()
void SkipTarget(ERenderTarget target, bool skip)
Turn off visibility for individual render targets.
GLdouble TModelUnit
Definition: gltypes.hpp:48
int gluProjectX(GLdouble objx, GLdouble objy, GLdouble objz, const GLdouble modelMatrix[16], const GLdouble projMatrix[16], const GLint viewport[4], GLdouble *winx, GLdouble *winy, GLdouble *winz)
Definition: glutils.hpp:223
CGlVboNode * AddGeomNode(GLenum node_type, const string &name, bool visible=true)
Add a geometry (vertex buffer object) node.
Definition: glmodel2d.cpp:97
virtual void LoadMatrixd(const GLdouble *m)=0
GLdouble m_ProjectionMatrix[16]
Definition: glmodel2d.hpp:132
void SetVertexBuffer2D(const vector< CVect2< float > > &data)
Definition: glvbonode.cpp:75
void Color4fv(const GLfloat *v)
Definition: irender.hpp:98
virtual void Scalef(GLfloat x, GLfloat y, GLfloat z)=0
static CGlResMgr & Instance()
Definition: glresmgr.cpp:59
T X() const
Definition: glpoint.hpp:59
virtual void Viewport(GLint x, GLint y, GLsizei width, GLsizei height)=0
void SetDefaultPosition()
Set 1 transformation and have it be the identity matrix.
T Height() const
Definition: glrect.hpp:90
GLdouble m_ModelviewMatrix[16]
Definition: glmodel2d.hpp:131
virtual void PointSize(GLfloat s)
Set point size for drawing: glPointSize()
Definition: glstate.cpp:419
virtual void Translatef(GLfloat x, GLfloat y, GLfloat z)=0
CVect2< TModelUnit > GetScale() const
Definition: glpane.cpp:128
virtual CMatrix4< float > GetProjectionMatrix() const =0
virtual void Enable(GLenum glstate)=0
void GetColorBuffer(vector< CRgbaColor > &data) const
Definition: glvbonode.cpp:110
bool OpenOrtho()
Definition: glpane.hpp:427
virtual void Begin(GLenum mode)=0
Start rendering.
virtual void PolygonMode(GLenum face, GLenum mode)
Set the polygon rasterization mode.
Definition: glstate.cpp:522
string GetName() const
Definition: globject.hpp:65
vector< CGlVboNode * > m_TempGeomNodes
Set of single-use rendernodes (which may use geom from m_Geom) These are deleted when ClearArrays is ...
Definition: glmodel2d.hpp:143
T Bottom() const
Definition: glrect.hpp:82
virtual void ScaleInvarient(bool b, CVect2< TModelUnit > scale=CVect2< TModelUnit >(TModelUnit(1), TModelUnit(1)))
Generic rendering options not specfically tied to OpenGL (or pdf..)
Definition: glstate.cpp:593
virtual CMatrix4< float > GetModelViewMatrix() const =0
T Width() const
Definition: glrect.hpp:86
virtual void MatrixMode(GLenum mode)=0
virtual void Render()
Set state and call x_Render() to render geometry.
IRender & GetGl()
convenience function for getting current render manager
CIRef< IVboGeom > FindGeomObject(const string &name)
Find a geometry object (just geometry - not a render node) by name.
Definition: glmodel2d.cpp:212
CIRef< IVboGeom > m_VBOGeom
subclass for vboset representing point, line, tri or quad geometry
Definition: glvbonode.hpp:127
void RectC(const TVPRect &rc)
Definition: irender.hpp:197
CVect2< TModelUnit > GetScaleFactor() const
Definition: glstate.hpp:327
TVPRect & GetViewport(void)
Definition: glpane.hpp:332
virtual void Enable(GLenum glstate)
glEnable() all options in m_Enabled
Definition: glstate.cpp:356
CIRef< IVboGeom > GetVBOGeom()
Definition: glvbonode.hpp:82
virtual TModelUnit TextWidth(const CGlTextureFont *font, const char *text) const =0
CGlState & GetState()
virtual void LineWidth(GLfloat w)
Set line width for drawing: glLineWidth()
Definition: glstate.cpp:410
virtual void LoadIdentity()=0
bool IsVisible() const
void SetPosition(const CMatrix4< float > &mat)
Set 1 transformation and have it be "mat".
virtual void PopMatrix()=0
virtual void LineCapStyle(ELineCapStyle c)
Set line cap ending style (pdf only)
Definition: glstate.cpp:610
CRef< CGlState > m_State
OpenGL state.
void SetVBOGeom(IVboGeom *geom)
Set/get geometry object. These can be shared between nodes.
Definition: glvbonode.hpp:79
T Left() const
Definition: glrect.hpp:81
T Y() const
Definition: glpoint.hpp:60
GLint m_Viewport[4]
For gluProject()
Definition: glmodel2d.hpp:130
void glColorC(const CRgbaColor &color)
Definition: glutils.hpp:177
virtual void ClearArrays()
clear any geometry vectors but do not update vertex buffers
Definition: glmodel2d.cpp:172
virtual void Disable(GLenum glstate)
glDisable() all options in m_Disabled
Definition: glstate.cpp:380
EFontFace GetFontFace() const
virtual void End()=0
Finish rendering (create buffer and send to renderer)
static bool CheckGlError()
Check if there are any OpenGL errors.
Definition: glutils.cpp:166
void Close(void)
Definition: glpane.cpp:178
IVboGeom::EVertexFormat GetVertexFormat() const
Definition: glvbonode.cpp:61
virtual void PolygonMode(GLenum face, GLenum mode)=0
Set the polygon rasterization mode.
size_t GetVertexCount() const
Definition: glvbonode.hpp:84
void Color4f(GLfloat r, GLfloat g, GLfloat b, GLfloat a)
Definition: irender.hpp:97
virtual void SetTexture(I3DTexture *tex)
Allow 1 texture for now (no multi-texturing)
Definition: glstate.cpp:404
virtual TModelUnit GetMetric(EMetric metric, const char *text=NULL, int len=-1) const
EFontFace
Set of pre-defined fonts for which we know we have valid font files.
void SetVisible(bool b)
Set/get node visibility.
TModelRect & GetVisibleRect(void)
Definition: glpane.hpp:357
virtual void LineJoinStyle(ELineJoinStyle s)
PDF-specific rendering state.
Definition: glstate.cpp:602
CGlRect< TModelUnit > TModelRect
Definition: gltypes.hpp:54
void Vertex2f(GLfloat x, GLfloat y)
Definition: irender.hpp:182
virtual void ShadeModel(GLenum mode)
Set shade model for default lighting: glShadeModel(GL_FLAT or GL_SMOOTH)
Definition: glstate.cpp:428
virtual void Disable(GLenum glstate)=0
glDisable()
virtual void Ortho(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble nearVal, GLdouble farVal)=0
void SetColorBuffer(const vector< CRgbaColor > &data)
Definition: glvbonode.cpp:103
virtual TModelUnit GetMetric(const CGlTextureFont *font, IGlFont::EMetric metric, const char *text=NULL, int len=-1) const =0
Calls the standard font metric functions except for pdf in which case it first replaces any bitmap fo...
virtual void BlendFunc(GLenum sfactor, GLenum dfactor)
Options to be used when GL_BLEND is enabled.
Definition: glstate.cpp:562
TModelUnit GetScaleX(void) const
Definition: glpane.cpp:118
virtual void Vertex3f(GLfloat x, GLfloat y, GLfloat z)=0
Explicit support not currently available for: GLbyte, GlShort and GLint calls, e.g.
TModelUnit GetScaleY(void) const
Definition: glpane.cpp:123
unsigned int GetFontSize() const
I3DTexture * GetTexture()
Return object holding the 1D texture.
virtual void Render(CGlPane &pane)
Draw to the screen.
Definition: glmodel2d.cpp:186
virtual void PushMatrix()=0
virtual void ColorC(const CRgbaColor &c)
Definition: glstate.cpp:449
CGlVboNode * AddTempGeomNode(const string &name, bool visible=true)
Add a geometry node of unspecified type (caller will have to allocate appropriate buffer type for the...
Definition: glmodel2d.cpp:236
TVPPoint Project(TModelUnit m_x, TModelUnit m_y) const
Definition: glpane.cpp:691
CGlVboNode * FindGeomNode(const string &name)
Find a geometry (vertex buffer object) node by name.
Definition: glmodel2d.cpp:88
CRgbaColor & GetColor(size_t i)
@ eMiteredJoin
Definition: glstate.hpp:77
@ eRoundedJoin
Definition: glstate.hpp:77
@ kVertexFormatVertex2D
Definition: ivbogeom.hpp:61
@ eRenderPDF
Definition: glstate.hpp:61
@ eButtCap
Definition: glstate.hpp:78
@ eRoundCap
Definition: glstate.hpp:78
@ eMetric_Descender
Definition: glfont.hpp:96
@ eMetric_CharHeight
Definition: glfont.hpp:76
unsigned char GetRedUC(void) const
Get specific channels in unsigned char values.
Definition: rgba_color.hpp:345
unsigned char GetGreenUC(void) const
Definition: rgba_color.hpp:351
const float * GetColorArray(void) const
Access the color array directly.
Definition: rgba_color.hpp:394
unsigned char GetBlueUC(void) const
Definition: rgba_color.hpp:357
TObjectType * GetNCPointer(void) const THROWS_NONE
Get pointer,.
Definition: ncbiobj.hpp:1174
TObjectType * GetPointer(void) THROWS_NONE
Get pointer,.
Definition: ncbiobj.hpp:998
void Reset(void)
Reset reference object.
Definition: ncbiobj.hpp:773
TObjectType & GetObject(void)
Get object.
Definition: ncbiobj.hpp:1011
TObjectType * GetPointerOrNull(void) THROWS_NONE
Get pointer value.
Definition: ncbiobj.hpp:986
#define END_NCBI_SCOPE
End previously defined NCBI scope.
Definition: ncbistl.hpp:103
#define BEGIN_NCBI_SCOPE
Define ncbi namespace.
Definition: ncbistl.hpp:100
double Elapsed(void) const
Return time elapsed since first Start() or last Restart() call (in seconds).
Definition: ncbitime.hpp:2776
void Start(void)
Start the timer.
Definition: ncbitime.hpp:2765
static const char label[]
<!DOCTYPE HTML >< html > n< header > n< title > PubSeq Gateway Help Page</title > n< style > n th
int i
yy_size_t n
#define abs(a)
Definition: ncbi_heapmgr.c:130
unsigned int a
Definition: ncbi_localip.c:102
EIPRangeType t
Definition: ncbi_localip.c:101
The NCBI C++/STL use hints.
Defines: CTimeFormat - storage class for time format.
T max(T x_, T y_)
T bound(T x_, T xlo_, T xhi_)
double r(size_t dimension_, const Int4 *score_, const double *prob_, double theta_)
vector< size_t > m_Labels
#define _ASSERT
Modified on Sat Apr 13 11:50:31 2024 by modify_doxy.py rev. 669887