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

Go to the SVN repository for this file.

1 /* $Id: phylo_tree_node.cpp 47479 2023-05-02 13:24:02Z ucko $
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>
37 #include <gui/opengl/irender.hpp>
38 #include <gui/objutils/utils.hpp>
39 
40 #include <cmath>
41 
42 
43 #define PHYLO_FEAT_LABEL "label"
44 #define PHYLO_FEAT_DIST "dist"
45 #define PHYLO_FEAT_SEQID "seq-id"
46 #define PHYLO_FEAT_TAXID "tax-id"
47 #define PHYLO_FEAT_CLUSTERID "cluster-id"
48 #define PHYLO_NODE_MARKER "marker"
49 
50 
51 #define PHYLO_NODE_COLOR "$NODE_COLOR"
52 #define PHYLO_EDGE_COLOR "$EDGE_COLOR"
53 #define EDGE_GRADIENT "$EDGE_GRADIENT"
54 #define PHYLO_NODE_COLLAPSED "$NODE_COLLAPSED"
55 #define PHYLO_NODE_BOUNDED "$NODE_BOUNDED"
56 
57 #define PHYLO_LABEL_COLOR "$LABEL_COLOR"
58 #define PHYLO_LABEL_BGCOLOR "$LABEL_BG_COLOR"
59 
60 #define PHYLO_NODE_SIZE "$NODE_SIZE"
61 #define PHYLO_SELECT_CLUSTERS "$SEL_CLUSTERS"
62 
63 #define MAX_PROPERTIES 255
64 
65 
67 
68 
69 ///////////////////////////////////////////////////////////////////////////////
70 // CPhyloTreeNode
71 ///////////////////////////////////////////////////////////////////////////////
72 
73 
75 {
76 }
77 
78 CPhyloTreeNode::CPhyloTreeNode(int x_id, double x_dist, const string & x_label)
79 {
80  GetValue().Set(x_id, x_dist, x_label);
81 }
82 
85 {
87 
88  // Sync expand/collapse feature value:
89  if (GetValue().GetDisplayChildren() == CPhyloNodeData::eHideChildren)
91  else // expanded is default, so no need to save it explicitly
93 }
94 
96 {
97  // don't do expand/cpllapse on root
98  if (!HasParent()) {
99  return false;
100  }
101  else if (chds == CPhyloNodeData::eShowChildren) {
102  return !Expanded();
103  }
104  else if (chds == CPhyloNodeData::eHideChildren) {
105  return !IsLeafEx();
106  }
107  return true;
108 }
109 
110 
112  const string & label)
113 {
115  GetValue().Sync(dict);
116 }
117 
118 ///////////////////////////////////////////////////////////////////////////////
119 // CPhyloNodeData
120 ///////////////////////////////////////////////////////////////////////////////
121 
123 
125 {
129 
130  m_Boundary = NULL;
131 
132  if (rhs.m_Boundary != NULL) {
134  }
135 }
136 
138 {
142 
143  delete m_Boundary;
144  m_Boundary = NULL;
145 
146  if (rhs.m_Boundary != NULL) {
148  }
149 
150  return *this;
151 }
152 
154 {
155  delete m_Boundary;
156  m_Boundary = NULL;
157 }
158 
159 
161  : m_ExtendedParms(NULL)
162 {
163  *this = rhs;
164 }
165 
167 {
168  m_SeqID = rhs.m_SeqID;
169  m_Features = rhs.m_Features;
170  m_NumLeaves = rhs.m_NumLeaves;
173  m_ClusterID = rhs.m_ClusterID;
174  m_ID = rhs.m_ID;
175  m_Label = rhs.m_Label;
176  m_Distance = rhs.m_Distance;
179  m_XY = rhs.m_XY;
180  m_IDX = rhs.m_IDX;
181  m_Angle = rhs.m_Angle;
182  m_DrawAngle = rhs.m_DrawAngle;
183  m_LabelRect = rhs.m_LabelRect;
186  m_Selected = rhs.m_Selected;
187  m_ColorType = rhs.m_ColorType;
188  m_Children = rhs.m_Children;
189  m_NodeWidth = rhs.m_NodeWidth;
195 
196  m_Size = rhs.m_Size;
198 
199  delete m_ExtendedParms;
201  if (rhs.m_ExtendedParms != NULL) {
203  }
204 
205  m_NodeColor = rhs.m_NodeColor;
206  m_FgColor = rhs.m_FgColor;
207 
208  return *this;
209 }
210 
212 {
213  delete m_ExtendedParms;
215 }
216 
218 {
219  if (!x_HasExtendedParms())
220  return false;
221 
222  return (m_ExtendedParms->m_SelClusters.size() > 0);
223 }
224 
226 {
227  if (!x_HasExtendedParms())
229 
231 }
232 
234 {
235  if (!x_HasExtendedParms())
237 
239 }
240 
242 {
243  if (!x_HasExtendedParms())
244  return false;
245 
246  return (m_ExtendedParms->m_MarkerColors.size() > 0);
247 }
248 
249 vector<CRgbaColor>& CPhyloNodeData::GetMarkerColors()
250 {
251  if (!x_HasExtendedParms())
253 
255 }
256 
258 {
259  if (!x_HasExtendedParms())
260  return 0.0f;
261  else
263 }
264 
266 {
267  if (!x_HasExtendedParms())
269 
271 }
272 
274 {
275  // marker colors should be in format:
276  // [r1,g1,b1,a1][r2,g2,b2,a2]....[rn,gn,bn,an], n = (1..n)
277 
278  string remainder = str;
279 
280  string marker_size_str = x_GetParameter(str, "size");
281  float marker_size = 2.0f;
282  if (marker_size_str != "") {
283  marker_size = NStr::StringToDouble(marker_size_str, NStr::fConvErr_NoThrow);
284  if (marker_size <= 0.0f) marker_size = 2.0f;
285  }
286  SetMarkerSize(marker_size);
287 
288  string::size_type idx = remainder.find_first_of(']');
289 
290  while (idx != string::npos) {
291  string color = remainder.substr(0, idx + 1);
292  size_t start_idx = remainder.find_first_of('[');
293  if (start_idx == string::npos)
294  return;
295  color = color.substr(start_idx, color.length() - start_idx);
296 
297  if (!x_HasExtendedParms())
299 
301 
302  remainder = remainder.substr(idx + 1, remainder.size() - (idx + 1));
303  idx = remainder.find_first_of(']');
304  }
305 }
306 
308 {
309  if (!x_HasExtendedParms())
310  return "";
311 
312  string c;
313 
314  for (size_t i = 0; i<m_ExtendedParms->m_MarkerColors.size(); ++i) {
315  // Convert to string format [r,g,b] where r,g,b are 0..255.
316  c += string("[") + m_ExtendedParms->m_MarkerColors[i].ToString(false, true) + std::string("] ");
317  }
318 
319  return c;
320 }
321 
323 {
324  if (!x_HasExtendedParms())
325  return eUnBounded;
326 
328 }
329 
331 {
332  if (!x_HasExtendedParms())
334 
337 
338  return m_ExtendedParms->m_Boundary;
339 }
340 
342 {
343  if (!x_HasExtendedParms())
344  return;
345 
346  delete m_ExtendedParms->m_Boundary;
348 }
349 
351  const string & name,
352  const string & value)
353 {
355 
356  if (dict.HasFeature(name)){
357  id = dict.GetId(name);
358  }
359  else { // find smallest available id
360  for (id=0; id < MAX_PROPERTIES; id++){
361  if (!dict.HasFeature(id)) {
362  dict.Register(id, name);
363  break;
364  }
365  }
366  if (id==MAX_PROPERTIES) {
368  "CPhyloTreeNode::SetFeature - maximum number of features exceeded");
369  }
370  }
372 }
373 
375  const string & name)
376 {
378 
379  if (dict.HasFeature(name)){
380  id = dict.GetId(name);
382  }
383 }
384 
387 {
388  const CBioTreeFeatureList & bfl = m_Features;
389 
390  const string& dist = bfl.GetFeatureValue(dict.GetId(PHYLO_FEAT_DIST));
391  if (!dist.empty()) {
392  try {
393  double ddist = NStr::StringToDouble(dist);
394  if (ddist < 0.0)
395  ddist = 0.0;
396  SetDistance(ddist);
397  }
398  catch(std::exception&) {}
399  }
400 
401  const string & size = bfl.GetFeatureValue(dict.GetId(PHYLO_NODE_SIZE));
402  SetNodeSize(-1.0f); // set to default size
403  if (!size.empty()) {
404  try {
405  //short isize = short(NStr::StringToInt(size));
407  SetNodeSize(isize);
408  }
409  catch(std::exception&) {}
410  }
411 
412  if (HasNodeMarker())
413  GetMarkerColors().clear();
414  const string & marker = bfl.GetFeatureValue(dict.GetId(PHYLO_NODE_MARKER));
415  if (!marker.empty()) {
416  try {
417  SetMarkerColors(marker);
418  }
419  catch(std::exception&){}
420  }
421 
422  // cluster ID if any
423  string cid = bfl.GetFeatureValue(dict.GetId(PHYLO_FEAT_CLUSTERID));
424  int cluster_id=-1;
425  if (!cid.empty()) {
426  int sel_id = NStr::StringToInt(cid, NStr::fConvErr_NoThrow);
427  if (sel_id || errno == 0)
428  cluster_id = sel_id;
429  }
430  SetClusterID(cluster_id);
431 
432 
433  // Clusters of selected nodes, if any
434  string sel_clusters = bfl.GetFeatureValue(dict.GetId(PHYLO_SELECT_CLUSTERS));
435  if (HasSelClusters())
437 
438  if (!sel_clusters.empty()) {
439  vector<CTempString> arr;
440  NStr::Split(sel_clusters, " ", arr);
441  for (size_t i=0; i<arr.size(); ++i) {
443  if (!sel_id && errno != 0)
444  continue;
445  GetSelClusters().push_back(sel_id);
446  }
447  }
448 
449 
450  // collapse/expand node
451  const string & ce = bfl.GetFeatureValue(dict.GetId(PHYLO_NODE_COLLAPSED));
454 
455  // node (and subtree) has bounding region (or not)
456  const string & bounded = bfl.GetFeatureValue(dict.GetId(PHYLO_NODE_BOUNDED));
457  if (!bounded.empty()) {
458  GetSubtreeBoundary()->CreateShapes(bounded);
459  }
460  else {
462  }
463 
464 
465  SetNodeFgColorIdx(-1);
467  SetLabelColorIdx(-1);
468  SetLabelBgColorIdx(-1);
469 
470  string node_color = bfl.GetFeatureValue(dict.GetId(PHYLO_NODE_COLOR));
471  size_t color_idx = -1;
472  if (!node_color.empty()) {
473  try {
474  CRgbaColor c(node_color);
475 
476  if (!t->FindColor(c, color_idx)) {
477  color_idx = t->AddColor(c);
478  }
479  SetNodeFgColorIdx((short)color_idx);
480  }
481  catch (CException&) {}
482  }
483 
484  node_color = bfl.GetFeatureValue(dict.GetId(PHYLO_EDGE_COLOR));
485  if (!node_color.empty()) {
486  try {
487  CRgbaColor c(node_color);
488 
489  if (!t->FindColor(c, color_idx)) {
490  color_idx = t->AddColor(c);
491  }
492  SetNodeEdgeColorIdx((short)color_idx);
493  }
494  catch (CException&) {}
495  }
496 
497  // Get gradient color property
498  node_color = bfl.GetFeatureValue(dict.GetId(EDGE_GRADIENT));
499  if (node_color != "") {
500  try {
501  m_EdgeColorGradient = NStr::StringToDouble(node_color) > 0.0 ? true : false;
502  }
503  catch (CException&) {}
504  }
505 
506  node_color = bfl.GetFeatureValue(dict.GetId(PHYLO_LABEL_COLOR));
507  if (!node_color.empty()) {
508  try {
509  CRgbaColor c(node_color);
510 
511  if (!t->FindColor(c, color_idx)) {
512  color_idx = t->AddColor(c);
513  }
514  SetLabelColorIdx((short)color_idx);
515  }
516  catch (CException&) {}
517  }
518  node_color = bfl.GetFeatureValue(dict.GetId(PHYLO_LABEL_BGCOLOR));
519  if (!node_color.empty()) {
520  try {
521  CRgbaColor c(node_color);
522 
523  if (!t->FindColor(c, color_idx)) {
524  color_idx = t->AddColor(c);
525  }
526  SetLabelBgColorIdx((short)color_idx);
527  }
528  catch (CException&) {}
529  }
530 }
531 
534 {
535  const CBioTreeFeatureList &bfl = m_Features;
536 
537  const string& sid = bfl.GetFeatureValue(dict.GetId(PHYLO_FEAT_SEQID));
538  if (!sid.empty()) {
539  try {
540  SetSeqID(new objects::CSeq_id(sid));
541  }
542  catch(CException& )
543  {
544  // try ad-hoc GI extraction (for misformed seq-id strings like: "gi|55823257|ref|YP_141698.1"
545  // (data coming from some other ad-hoc scripts)
546  //
547  try {
548  string gi_str;
549  CSeqUtils::GetGIString(sid, &gi_str);
550  if (!gi_str.empty()) {
551  SetSeqID(new objects::CSeq_id(gi_str));
552  }
553  else {
554  string lcl_sid = "lcl|";
555  lcl_sid.append(sid);
556  SetSeqID(new objects::CSeq_id(lcl_sid));
557  }
558  }
559  catch(std::exception&)
560  {
561  }
562 
563  }
564  catch(std::exception&)
565  {
566  }
567  }
568 
569  InitFeatures(dict, t);
570 }
571 
573 {
574  string tmp;
576 
579 
581  SetFeature(dict, PHYLO_NODE_COLLAPSED, "1");
582  else // expanded is default, so no need to save it explicitly
584 
585  if (GetClusterID() == -1) // No need for empty ids
587 
588  // Not sure we need to save these if we save all selection
589  // info in user-data.
590  if (HasSelClusters()) {
591  string sel_ids;
592  for (size_t i=0; i<GetSelClusters().size(); ++i) {
593  string sel_id;
594  NStr::IntToString(sel_id, GetSelClusters()[i]);
595  if (i>0)
596  sel_ids += " ";
597  sel_ids += sel_id;
598  }
599  SetFeature(dict, PHYLO_SELECT_CLUSTERS, sel_ids);
600  }
601  else {
603  }
604 }
605 
607 {
608  return m_Features;
609 }
610 
612 {
613  m_Features = btcfl;
614 }
615 
617 {
618  if (HasSelClusters())
619  return m_ExtendedParms->m_SelClusters[0];
620 
621  if (m_ClusterID != -1) {
622  return m_ClusterID;
623  }
624 
625  return -1;
626 }
627 
629 {
630  // This is for the clustering algo so when there are multiple
631  // selection clusters it can set up a marker with each of
632  // those. So return the selection clusters size, unless
633  // 0, in which case we return number based on cluster ID.
634  if (HasSelClusters())
635  return m_ExtendedParms->m_SelClusters.size();
636 
637  return (m_ClusterID != -1 ? 1 : 0);
638 }
639 
641 {
642  m_ID = x_id;
643 }
644 
645 string CPhyloNodeData::x_GetParameter(const string& features, const string& parm)
646 {
647  string parm_lower = parm;
648  parm_lower = NStr::ToLower(parm_lower) + "=";
649 
650  string features_lower = features;
651  features_lower = NStr::ToLower(features_lower);
652 
653  size_t idx = features_lower.find(parm_lower);
654  if (idx != string::npos) {
655  size_t end_idx = features.find_first_of(" ,\t", idx);
656  if (end_idx == string::npos)
657  end_idx = features.size();
658 
659  return features.substr(idx + parm_lower.length(), end_idx-(idx+parm_lower.length()));
660  }
661 
662  return "";
663 }
664 
665 // Get angle after screen is scaled (compressed/stretched) aniostropically
666 float CPhyloNodeData::GetScaledAngle(const CVect3<float>& scale, float a, bool for_label) const
667 {
668  // Angle is unscaled so multiple x/y by inverse scale and recompute angle
669  // to get actual screen angle after scaling
670  float cos_a = cosf(a) / scale.X();
671  float sin_a = sinf(a) / scale.Y();
672  a = atan2f(sin_a, cos_a);
673 
674  // rotation for angles >90 and <270 is different since text those
675  // labels end (not start) at the node
676  if (for_label && cos_a < 0.0f) {
677  a = a - M_PI;
678  }
679 
680  return a;
681 }
682 
684  CPhyloTreeScheme* scheme,
685  float& node_size,
686  float size_scaler) const
687 {
689 
690  // Get size of node possibly modified if it is collapsed
691  node_size = GetDefaultNodeSize(scheme);
692 
693  // If not expanded:
695  if (m_Angle != 0.0f) {
696  float a = GetScaledAngle(scale, m_Angle, false);
697 
698  // Bigger collapsed nodes start at end of branch and extend out, so when drawing
699  // a highlight, it may look worse hanging out past the end of the branch.
700  p.X() += cosf(a) * node_size * size_scaler * scale.X();
701  p.Y() += sinf(a) * node_size * size_scaler * scale.Y();
702  }
703  else {
704  p.X() += node_size * size_scaler * scale.X();
705  }
706  }
707 
708  return p;
709 }
710 
712  const CGlTextureFont& font,
713  CRgbaGradColorTable* color_table,
714  const CVect3<float>& scale,
715  bool truncate_labels,
716  TModelUnit max_len)
717 {
718  if (!m_Visible || m_AlreadyDrawn || m_Text.empty())
719  return;
720 
722  TModelUnit pos_xmin;
723  TModelUnit pos_xmax;
724  TModelUnit pos_y;
725 
726  r = GetLabelRect();
727 
728  pos_xmin = (TModelUnit)(X() + (r.Left() * scale.X()));
729  pos_xmax = (TModelUnit)(X() + (r.Right() * scale.X()));
730  pos_y = (TModelUnit)(Y() + (r.Bottom() * scale.Y()));
731 
732  string text_out = m_Text;
733 
734  TModelUnit text_len = 0.0;
735  TModelUnit vp_width = (TModelUnit)pane.GetViewport().Width();
736  TModelUnit tw = font.TextWidth(m_Text.c_str());
737 
738  if (truncate_labels) {
739  TModelUnit screen_minx = pane.ProjectX(pos_xmin);
740  TModelUnit screen_maxx = pane.ProjectX(pos_xmax);
741 
742  if (cos(GetAngle()) >= 0.0) {
743  text_len = std::min(tw, vp_width - screen_minx);
744  }
745  else {
746  text_len = std::min(tw, screen_maxx);
747  }
748  }
749 
750  // max_len is in screen (pixel) coordinates
751  if (max_len > 0.0) {
752  text_len = std::min(text_len, max_len);
753  }
754 
755  // Trim the string if the target length is > 0 and < the strings
756  // current length
757  if (text_len > 0.0 && text_len < tw) {
758  if (cos(GetAngle()) >= 0.0) {
759  text_out = font.Truncate(m_Text.c_str(), text_len);
760  }
761  else {
762  std::reverse(text_out.begin(), text_out.end());
763  text_out = font.Truncate(text_out.c_str(), text_len);
764  std::reverse(text_out.begin(), text_out.end());
765 
766  // Text is trimmed but since it ends at the node we have to move the
767  // start of the text in the direction of the node by the amount
768  // that we trimmed:
769  TModelUnit new_width = font.TextWidth(text_out.c_str());
770 
771  pos_xmin += (tw - new_width)*scale.X();
772  }
773 
774  if (text_out == "...")
775  return;
776  }
777 
778  IRender& gl = GetGl();
779 
780  // Draw label background, if it has one specified
781  if (m_LabelBgColorIdx != -1) {
782  CRgbaColor c = color_table->GetColor(m_LabelBgColorIdx);
783  gl.Color4fv(c.GetColorArray());
784 
786  TModelUnit text_w = font.TextWidth(text_out.c_str());
787 
788  gl.Enable(GL_BLEND);
789  gl.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
790  gl.PolygonMode(GL_FRONT_AND_BACK, GL_FILL);
791 
792  gl.Begin(GL_TRIANGLE_STRIP);
793  gl.Vertex2d(pos_xmin - 1.0 * pane.GetScaleX(), pos_y + (text_h + 1.0) * pane.GetScaleY());
794  gl.Vertex2d(pos_xmin - 1.0 * pane.GetScaleX(), pos_y - 1.0*pane.GetScaleY());
795  gl.Vertex2d(pos_xmin + (text_w + 1.0) * pane.GetScaleX(), pos_y + (text_h + 1.0) * pane.GetScaleY());
796  gl.Vertex2d(pos_xmin + (text_w + 1.0) * pane.GetScaleX(), pos_y - 1.0*pane.GetScaleY());
797  gl.End();
798  }
799 
801  SetDrawAngle(0.0f);
802 
803  font.TextOut(pos_xmin, pos_y, text_out.c_str());
804 }
805 
807  const CGlTextureFont& font,
808  CRgbaGradColorTable* color_table,
809  const CVect3<float>& scale,
810  float orig_angle,
811  bool truncate_labels)
812 {
813  if (!m_Visible || m_AlreadyDrawn)
814  return;
815 
816  float angle;
817  CVect4<CVect2<float> > corners = GetRotatedTextBox(scale, angle, orig_angle);
818 
819  float angle_degrees = angle * (360.0f / (2.0f*float(M_PI)));
820 
821  IRender& gl = GetGl();
822 
823  // Draw label background, if it has one specified
824  if (m_LabelBgColorIdx != -1) {
825  CRgbaColor c = color_table->GetColor(m_LabelBgColorIdx);
826  gl.Color4fv(c.GetColorArray());
827 
828  gl.Enable(GL_BLEND);
829  gl.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
830  gl.PolygonMode(GL_FRONT_AND_BACK, GL_FILL);
831 
832  gl.Begin(GL_TRIANGLE_STRIP);
833  gl.Vertex2f(corners[3].X(), corners[3].Y());
834  gl.Vertex2f(corners[0].X(), corners[0].Y());
835  gl.Vertex2f(corners[2].X(), corners[2].Y());
836  gl.Vertex2f(corners[1].X(), corners[1].Y());
837  gl.End();
838  }
839 
840  string text_out = m_Text;
841  if (truncate_labels) {
842  // Find bounding box for text rectangle:
843  float minx = 1e10f;
844  float miny = 1e10f;
845  float maxx = -1e10f;
846  float maxy = -1e10f;
847  for (size_t i = 0; i < 4; ++i) {
848  minx = std::min(corners[i].X(), minx);
849  miny = std::min(corners[i].Y(), miny);
850  maxx = std::max(corners[i].X(), maxx);
851  maxy = std::max(corners[i].Y(), maxy);
852  }
853 
854  // Get viewport (pixel) coordinates of bounding box:
855  TModelUnit screen_maxx = pane.ProjectX(maxx);
856  TModelUnit screen_minx = pane.ProjectX(minx);
857  TModelUnit screen_miny = pane.ProjectY(miny);
858  TModelUnit screen_maxy = pane.ProjectY(maxy);
859 
860  TVPPoint p1 = pane.Project(corners[0].X(), corners[0].Y());
861  TVPPoint p2 = pane.Project(corners[1].X(), corners[1].Y());
862  CVect2<TModelUnit> text_box_vec(p2.X() - p1.X(), p2.Y() - p1.Y());
863  TModelUnit text_box_len = text_box_vec.Length();
864 
865  TModelUnit pct = 1.0;
866  TModelUnit vp_width = (TModelUnit)pane.GetViewport().Width();
867  TModelUnit vp_height = (TModelUnit)pane.GetViewport().Height();
868 
869  // Trim the string if it extends past the viewport's borders of
870  // (0,0, vp_width, vp_height)
871 
872  // In positive (cos > 0) direction text starts at the node
873  if (cos(orig_angle) >= 0.0) {
874  // If text extends past vp_width:
875  if (screen_minx < vp_width && screen_maxx > vp_width) {
876  pct = (vp_width - screen_minx) / (screen_maxx - screen_minx);
877  }
878  // If text extends past vp_height:
879  if (screen_miny < vp_height && screen_maxy > vp_height) {
880  pct = std::min(pct, (vp_height - screen_miny) / (screen_maxy - screen_miny));
881  }
882  // If text textends below y=0:
883  else if (screen_maxy > 0.0 && screen_miny < 0.0) {
884  pct = std::min(pct, (screen_maxy) / (screen_maxy - screen_miny));
885  }
886 
887  // Trim text if needed:
888  if (pct < 1.0) {
889  text_out = font.Truncate(m_Text.c_str(), text_box_len*pct);
890  }
891  }
892  // In negative (cos < 0) direction text ends at node so we truncate text
893  // beginning, not the end
894  else {
895  // If text starts before x=0:
896  if (screen_minx < 0.0 && screen_maxx > 0.0) {
897  pct = (screen_maxx) / (screen_maxx - screen_minx);
898  }
899  // If text starts above vp_height:
900  if (screen_miny < vp_height && screen_maxy > vp_height) {
901  pct = std::min(pct, (vp_height - screen_miny) / (screen_maxy - screen_miny));
902  }
903  // If text starts below y=0:
904  else if (screen_maxy > 0.0 && screen_miny < 0.0) {
905  pct = std::min(pct, (screen_maxy) / (screen_maxy - screen_miny));
906  }
907 
908  // Trim text if needed:
909  if (pct < 1.0) {
910  TModelUnit tw = font.TextWidth(m_Text.c_str());
911 
912  // Reverse the text so that the beginning (left side) is truncated
913  // then set width to total width - width of text to left of viewport
914  std::reverse(text_out.begin(), text_out.end());
915  text_out = font.Truncate(text_out.c_str(), text_box_len*pct);
916  std::reverse(text_out.begin(), text_out.end());
917 
918  // Text is trimmed but since it ends at the node we have to move the
919  // start of the text in the direction of the node by the amount
920  // that we trimmed:
921  TModelUnit new_width = font.TextWidth(text_out.c_str());
922 
923  CVect2<float> text_dir = corners[1] - corners[0];
924 
925  float delta = float((tw-new_width)/tw);
926  corners[0] = corners[0] + text_dir * delta;
927  }
928  }
929  if (text_out == "...")
930  return;
931  }
932 
934  SetDrawAngle(angle);
935 
936  font.BeginText();
937  font.WriteText(corners[0].X(), corners[0].Y(), text_out.c_str(), TModelUnit(angle_degrees));
938  font.EndText();
939 }
940 
941 /// Return text box (m_LabelRect) rotated to align with radial edges
943  float& angle, float orig_angle) const
944 {
947 
948  angle = GetScaledAngle(scale, m_Angle);
949 
950  float cos_a = cosf(angle);
951  float sin_a = sinf(angle);
952 
953  CVect2<float> dir(0.0f, 0.0f);
954  float overhang = GetNodeOverhang(CVect2<float>(scale.X(), scale.Y()));
955  if (overhang > 0.0f) {
956  if (orig_angle < 0.0f)
957  overhang *= -1.0f;
958  dir.Set(cosf(orig_angle)*overhang*scale.X(), sinf(orig_angle)*overhang*scale.Y());
959  }
960 
961  // First corner is (left, bottom)
962  for (int corner=0; corner<4; ++corner) {
963  CGlPoint<float> pos = r.GetCorner(corner);
964 
965  // multiply corner by standard 2D rotation matrix:
966  CVect2<float> rpos((pos.X())*cos_a-pos.Y()*sin_a, (pos.X())*sin_a + pos.Y()*cos_a);
967  //CVect2<float> rpos((overhang + pos.X())*cos_a - pos.Y()*sin_a, (overhang + pos.X())*sin_a + pos.Y()*cos_a);
968  rpos.X() = X() + scale.X()*rpos.X() + dir.X();
969  rpos.Y() = Y() + scale.Y()*rpos.Y() + dir.Y();
970  result[corner] = rpos;
971  }
972 
973  return result;
974 }
975 
976 /// Return the text starting point rotated to align with radial edges
978  float& angle) const
979 {
981 
982  angle = GetScaledAngle(scale, m_Angle);
983  float cos_a = cosf(angle);
984  float sin_a = sinf(angle);
985 
986  // Vector from node to lower left corner of text
987  CVect2<float> tp(r.Left(), r.Bottom());
988 
989  CVect2<float> tpr(tp.X()*cos_a-tp.Y()*sin_a, tp.X()*sin_a + tp.Y()*cos_a);
990 
991  // position of text (which will be rotated) is the rotated offset tpr
992  CVect2<float> result(X() + tpr.X()*scale.X(),
993  Y() + tpr.Y()*scale.Y());
994 
995  return result;
996 }
997 
999  const CGlTextureFont& font,
1000  const CVect3<float>& scale,
1001  bool truncate_labels,
1002  string& text_out)
1003 {
1004  CGlRect<float> r;
1005  CVect2<float> pos;
1006 
1007  r = GetLabelRect();
1008 
1009  pos.X() = (float)(X() +
1010  (r.Left() * scale.X()));
1011  pos.Y() = (float)(Y() +
1012  (r.Bottom() * scale.Y()));
1013 
1014 
1015  if (truncate_labels) {
1016  float screen_x = (float)(pane.ProjectX(pos.X()));
1017 
1018  // Label may go off right side of screen so see if it has
1019  // to be truncated on the right;
1020  if (screen_x > 0.0f) {
1021  float w = ((float)pane.GetViewport().Width()-screen_x);
1022  text_out = font.Truncate(m_Text.c_str(), w);
1023  }
1024  // Label starts before left side of screen (definitly clipped)
1025  // so truncate it on the left
1026  else {
1027  text_out = m_Text;
1028  // Reverse the text so that the beginning (left side) is truncated
1029  // then set width to total width - width of text to left of viewport
1030  std::reverse(text_out.begin(), text_out.end());
1031  text_out = font.Truncate(text_out.c_str(), r.Width()+screen_x);
1032  std::reverse(text_out.begin(), text_out.end());
1033  // After truncation, draw text from left edge of viewport
1034  pos.X() = (float)pane.UnProjectX(0.0);
1035  }
1036  }
1037  else {
1038  text_out = m_Text;
1039  }
1040 
1041  return pos;
1042 }
1043 
1044 
1046  CVect2<float>& lower_left,
1047  CVect2<float>& upper_right,
1048  bool rotated)
1049 {
1051 
1052  if (!rotated || r.Width() == 0.0f || r.Height() == 0.0f) {
1053  lower_left.X() = X() + r.Left()*scale.X();
1054  lower_left.Y() = Y() + r.Bottom()*scale.Y();
1055 
1056  upper_right.X() = X() + r.Right()*scale.X();
1057  upper_right.Y() = Y() + r.Top()*scale.Y();
1058  }
1059  else {
1060  lower_left.X() = std::numeric_limits<float>::max();
1061  lower_left.Y() = std::numeric_limits<float>::max();
1062 
1063  upper_right.X() = -std::numeric_limits<float>::max();
1064  upper_right.Y() = -std::numeric_limits<float>::max();
1065 
1066 
1067  float ang;
1068  CVect3<float> s3(scale.X(), scale.Y(), 1.0f);
1069  CVect4<CVect2<float> > corners = GetRotatedTextBox(s3, ang);
1070 
1071  for (int corner=0; corner<4; ++corner) {
1072  lower_left.X() = std::min(lower_left.X(), corners[corner].X());
1073  lower_left.Y() = std::min(lower_left.Y(), corners[corner].Y());
1074 
1075  upper_right.X() = std::max(upper_right.X(), corners[corner].X());
1076  upper_right.Y() = std::max(upper_right.Y(), corners[corner].Y());
1077  }
1078  }
1079 }
1080 
1082  CVect2<float> pt,
1083  bool rotated)
1084 {
1086 
1087  // Put the selection position in pixel coordinates relative to the node
1088  // since that's how text box coordinates are stored.
1089  pt.X() -= X();
1090  pt.Y() -= Y();
1091 
1092  pt.X() *= 1.0f/scale.X();
1093  pt.Y() *= 1.0f/scale.Y();
1094 
1095  if (rotated && m_DrawAngle != 0.0f) {
1096  // Rotate the selection point by the opposite angle rather than
1097  // rotating the whole text box
1098  float a = -m_DrawAngle;
1099 
1100  // rotate point around node:
1101  float cos_a = cosf(a);
1102  float sin_a = sinf(a);
1103  CVect2<float> rpos(pt.X()*cos_a-pt.Y()*sin_a, pt.X()*sin_a + pt.Y()*cos_a);
1104  pt = rpos;
1105  }
1106 
1107  // Is point inside text box (using pixel coords)?
1108  if (r.PtInRect(pt.X(), pt.Y()))
1109  return true;
1110  else
1111  return false;
1112 
1113 }
1114 
1116 {
1117  if (!rotated) {
1118  return GetLabelRect();
1119  }
1120  else {
1122 
1127 
1128  float a = m_Angle;
1129 
1130  // Angle is unscaled so multiple x/y by inverse scale and recompute angle
1131  // to get actual screen angle after scaling
1132  float cos_a = cosf(a)*1.0f/scale.X();
1133  float sin_a = sinf(a)*1.0f/scale.Y();
1134  a = atan2f(sin_a, cos_a);
1135 
1136  // rotation for angles >90 and <270 is different since text for those
1137  // labels ends (not starts) at the node
1138  if (cos_a < 0.0f) {
1139  a = a-M_PI;
1140  }
1141 
1142  cos_a = cosf(a);
1143  sin_a = sinf(a);
1144 
1145  // First corner is (left, bottom)
1146  for (int corner=0; corner<4; ++corner) {
1147  CGlPoint<float> pos = r.GetCorner(corner);
1148 
1149  // multiply corner by standard 2D rotation matrix:
1150  CVect2<float> rpos(pos.X()*cos_a-pos.Y()*sin_a, pos.X()*sin_a + pos.Y()*cos_a);
1151 
1152  rr.SetLeft(std::min(rr.Left(), rpos.X()));
1153  rr.SetRight(std::max(rr.Right(), rpos.X()));
1154  rr.SetBottom(std::min(rr.Bottom(), rpos.Y()));
1155  rr.SetTop(std::max(rr.Top(), rpos.Y()));
1156  }
1157 
1158  return rr;
1159  }
1160 }
1161 
1163  CVect2<float>& lower_left,
1164  CVect2<float>& upper_right,
1165  bool rotated)
1166 {
1167  GetLabelRect(scale, lower_left, upper_right, rotated);
1168 
1169  float deltax = m_NodeSize*scale.X() + std::abs(m_NodeOffset.X());
1170  float deltay = m_NodeSize*scale.Y() + std::abs(m_NodeOffset.Y());
1171 
1172  lower_left.X() = std::min(lower_left.X(), X()-deltax);
1173  lower_left.Y() = std::min(lower_left.Y(), Y()-deltay);
1174  upper_right.X() = std::max(upper_right.X(), X()+deltax);
1175  upper_right.Y() = std::max(upper_right.Y(), Y()+deltay);
1176 }
1177 
1179 {
1180  m_Visible = b;
1181 }
1182 
1184 {
1185  return (X() + (GetLabelRect().Left() * scale.X()));
1186 }
1187 
1189 {
1190  float forced_size = GetNodeSize();
1191  float def_node_size = 0;
1192 
1193  if (forced_size < 0.0f) {
1194  if (GetDisplayChildren() == eHideChildren) {
1195  if (scheme->GetBoaNodes()) {
1196  double max_child_size = scheme->GetMaxNumChildren();
1197  double min_child_size = scheme->GetMinNumChildren();
1198  double this_childs_size = std::min(max_child_size, double(GetNumLeaves() + 2));
1199 
1200  double min_node_size = scheme->GetMinNodeSize();
1201  double max_node_size = scheme->GetMaxNodeSize();
1202 
1203  def_node_size = (float)(min_node_size + (max_node_size - min_node_size) *
1204  (log(this_childs_size) - log(min_child_size)) /
1205  (log(max_child_size) - log(min_child_size)));
1206  }
1207  else {
1208  // Make all collapsed nodes a little bigger than regular ones
1209  def_node_size = (float)scheme->GetNodeSize()*1.5;
1210  }
1211  }
1212  else if (GetNumLeavesEx() > 0) {
1213  def_node_size = (float)scheme->GetNodeSize();
1214  }
1215  else {
1216  def_node_size = (float)scheme->GetLeafNodeSize();
1217  }
1218  }
1219  else {
1220  def_node_size = (float)forced_size;
1221  }
1222 
1223  return def_node_size;
1224 }
1225 
1227 {
1228  // For layout, smallest size is scheme->GetNodeSize(), otherwise parent nodes (of this size)
1229  // may be forced into overlapping (and 0-sized nodes mess up layout which uses node sizes for spacing)
1230  float size = GetDefaultNodeSize(scheme);
1231  if (size < (float)scheme->GetNodeSize())
1232  size = (float)scheme->GetNodeSize();
1233 
1234  return std::max(size, 1.0f);
1235 }
1236 
1238 {
1239  // If this function returns 0 (tree without distance) caller should
1240  // use default distance
1241  m_NodeWidth = 0.0f;
1242 
1243  double max_branch_dist = scheme->GetMaxBranchDist();
1244  if (scheme->GetBoaNodes() &&
1246  max_branch_dist > 1e-04f) {
1247 
1248  double min_width = scheme->GetMinNodeSize();
1249  double max_width = scheme->GetMaxNodeSize();
1250 
1251  // Rescale branch distance which goes from 0 to max_branch_dist
1252  // to be in the range scheme->GetMinNumChildren()..scheme->GetMaxNumChildren()
1253  // which is the range we use for node size (height) in GetDefaultNodeSize
1254  double max_dist = scheme->GetMaxNumChildren();
1255  double min_dist = scheme->GetMinNumChildren();
1256 
1257  float scaled_max_child_dist = (m_MaxChildDistance / max_branch_dist)*(max_dist - min_dist) + min_dist;
1258 
1259  // We multiply by 4 here to get more length than width in our collapsed
1260  // nodes since width crowds out other things more than length does.
1261  m_NodeWidth = 4.0f*((float)(min_width + (max_width - min_width) *
1262  (log(scaled_max_child_dist) - log(min_dist)) /
1263  (log(max_dist) - log(min_dist))));
1264  }
1265  else {
1266  m_NodeWidth = 2.0f*GetDefaultNodeSize(scheme);
1267  }
1268 
1269  return m_NodeWidth;
1270 }
1271 
1273 {
1274  // Only interested in this for collapsed nodes which vary in size and width
1276  CVect2<float> pix_offset(m_NodeOffset.X() / scale.X(), m_NodeOffset.Y() / scale.Y());
1277 
1278  pix_offset += m_NodePixelOffset;
1279 
1280  // we subtract abs(m_LabelRect.Left()) becuase this is the distance that we already offset
1281  // the label from the node, and this overhang is used to consider additional offset.
1282  float label_dist = std::min(std::abs(m_LabelRect.Left()), std::abs(m_LabelRect.Right()));
1283  float total_extension = -pix_offset.Length() + m_NodeWidth - label_dist;
1284 
1285  return total_extension > 0.0f ? total_extension : 0.0f;
1286  }
1287 
1288  return 0.0f;
1289 }
1290 
Feature dictionary.
Definition: bio_tree.hpp:176
Features storage for the bio tree node.
Definition: bio_tree.hpp:101
class CGlPane
Definition: glpane.hpp:62
CSubtreeBoundary * GetSubtreeBoundary()
Gets current boundary or creates a new one if m_Boundary is NULL.
bool PointInTextBox(const CVect2< float > &scale, CVect2< float > pt, bool rotated=false)
Return true if pt is inside of this nodes text box.
const TLabel & GetLabel() const
void SetClusterID(TClusterID x_id)
TClusterID m_ClusterID
void DeleteSubtreeBoundary()
Deletes current boundary (if not NULL).
TSelectedState m_Selected
CVect2< float > m_NodeOffset
void SetLabelBgColorIdx(short idx)
float m_NodeWidth
This is computed by GetNodeWidthScaler(..) for collapsed nodes and we need to hang onto it for node l...
float GetNodeOverhang(const CVect2< float > &scale) const
Get extenstion of node beyond end of edge in pixels.
TSelClusterIDs & GetSelClusters()
CRef< objects::CSeq_id > m_SeqID
int GetNumLeaves() const
void Init(const CBioTreeFeatureDictionary &dict, CRgbaGradColorTable *t)
TBoundingState GetBoundedDisplay() const
CGlRect< float > m_LabelRect
TLabel m_Label
Full label.
void SetVisible(bool b)
Flag to renderer to determine whether to draw label.
void SetNodeFgColorIdx(short idx)
bool m_AlreadyDrawn
Text is alpha-blended so we add a flag to prevent drawing multiple times.
bool x_HasExtendedParms() const
void Sync(CBioTreeFeatureDictionary &dict)
void RenderRotated(const CGlPane &pane, const CGlTextureFont &font, CRgbaGradColorTable *color_table, const CVect3< float > &scale, float orig_angle, bool truncate_labels)
Draw the label and rotate it to match m_Angle (radial text) This form does not support label truncati...
void SetDistance(TDistance x_dist)
static const TColor TNoColor
SExtendedNodeParms * m_ExtendedParms
void SetId(TID x_id)
CRgbaColor m_FgColor
Current text color.
int GetNumLeavesEx() const
short m_NodeEdColorIdx
Node colors defined by scheme.
void SetSeqID(objects::CSeq_id *sid)
void SetBioTreeFeatureList(const CBioTreeFeatureList &btcfl)
CVect2< float > GetNodePosEx(const CVect3< float > &scale, CPhyloTreeScheme *scheme, float &node_size, float size_scaler=1.0f) const
Get modified center of node position - this works for collapsed nodes in rotated layouts and with off...
CVect2< float > GetTextOut(CGlPane &pane, const CGlTextureFont &font, const CVect3< float > &scale, bool truncate_labels, string &text_out)
Return the drawing position and (possibly truncated) text.
void RemoveFeature(CBioTreeFeatureDictionary &dict, const string &name)
void SetLabelColorIdx(short idx)
bool HasNodeMarker() const
int GetPrimaryCluster() const
With selection clusters a node may have multiple cluster ids.
size_t GetNumClusters() const
Return total # of applicable clusters - selection + m_ClusterID.
float GetNodeSize() const
float GetMarkerSize() const
void SetDrawAngle(float angle)
void SetSelClusters(const TSelClusterIDs &sc)
float GetNodeWidthScaler(const CPhyloTreeScheme *scheme) const
Get modified node width (length) for collapsed nodes. Default is 1.
bool HasSelClusters() const
void SetMarkerColors(const string &str)
float GetNodeLayoutSize(const CPhyloTreeScheme *scheme) const
Get modified node size - use this instead of GetDefaultNodeSize when doing layout (doesn't go to 0 if...
string GetMarkerColorsAsString()
void SetMarkerSize(float f)
short m_LabelFgColorIdx
Label color.
float GetScaledAngle(const CVect3< float > &scale, float a, bool for_label=true) const
Utility to get screen rotation angle after scaling.
vector< CRgbaColor > & GetMarkerColors()
void InitFeatures(const CBioTreeFeatureDictionary &dict, CRgbaGradColorTable *t)
TDistance m_MaxChildDistance
void SetNodeEdgeColorIdx(short idx)
TClusterID GetClusterID(void) const
string x_GetParameter(const string &features, const string &parm)
void GetBoundingRect(const CVect2< float > &scale, CVect2< float > &lower_left, CVect2< float > &upper_right, bool rotated=false)
Find the rectangle for the node and label combined given the current zoom level (scale)
void SetNodeSize(float x_sz)
float GetAngle(void) const
void Render(const CGlPane &pane, const CGlTextureFont &font, CRgbaGradColorTable *color_table, const CVect3< float > &scale, bool truncate_labels, TModelUnit max_len=-1.0f)
Draw the label using scale to compute its offset from m_BasePos.
CVect2< float > GetRotatedTextPos(const CVect3< float > &scale, float &angle) const
Return the text starting point rotated to align with radial edges.
void Set(TID x_id, TDistance x_dist, const TLabel &x_label)
CGlRect< float > GetLabelRect() const
float GetDefaultNodeSize(const CPhyloTreeScheme *scheme) const
Get modified node size - includes scaled (BOA) size.
CPhyloNodeData & operator=(const CPhyloNodeData &rhs)
void SetLabel(const TLabel &x_label)
TDisplayChildren GetDisplayChildren() const
TDistance m_DistanceFromRoot
bool m_Children
expand-collapse state (expanded==true)
float GetMinX(const CVect2< float > &scale)
Return labels minimal X coordinate.
void SetDisplayChildren(TDisplayChildren show)
CVect4< CVect2< float > > GetRotatedTextBox(const CVect3< float > &scale, float &angle, float orig_angle=0.0f) const
Return text box (m_LabelRect) rotated to align with radial edges.
vector< int > TSelClusterIDs
string m_Text
Text to render.
CBioTreeFeatureList & GetBioTreeFeatureList()
objects::CNode::TId TID
CRgbaColor m_NodeColor
Current node color.
bool m_EdgeColorGradient
Controls use of gradient coloring for edges - if false, edges will be a single color,...
bool m_Visible
True if node is visible.
CPhyloTreeScheme::TPhyloTreeColors m_ColorType
float m_NodeSize
Scaled node size.
TDistance GetDistance() const
CBioTreeFeatureList m_Features
CVect2< float > m_NodePixelOffset
Pixel offset to apply the node.
void SetFeature(CBioTreeFeatureDictionary &dict, const string &name, const string &value)
bool Expanded() const
Return true if node is currently not collapsed.
void ExpandCollapse(CBioTreeFeatureDictionary &dict, CPhyloNodeData::TDisplayChildren chds)
Set this node to be expanded/collapsed.
bool CanExpandCollapse(CPhyloNodeData::TDisplayChildren chds)
Return true if node can have its expand/collapsed state changed to chds.
void SetLabel(CBioTreeFeatureDictionary &dict, const string &label)
Set label string and synch value to the feature list for this ndoe.
bool IsLeafEx() const
Return true if node is a leaf or is collapsed.
GLdouble GetMaxNumChildren() const
GLdouble GetMaxNodeSize() const
size range for variable-sized collapsed nodes (so min node size here may be greater than node size)
GLdouble GetMaxBranchDist() const
And we scale the length of the collapsed node marker based on the max.
GLdouble GetLeafNodeSize() const
GLdouble GetMinNumChildren() const
collapsed node sizes are scaled from min to max values based on number of children so we need to have...
bool GetBoaNodes() const
GLdouble GetMinNodeSize() const
GLdouble GetNodeSize() const
class CRgbaColor provides a simple abstraction for managing colors.
Definition: rgba_color.hpp:58
CRgbaGradColorTable Provides a storage for colors (to eliminate color creation overhead) and Function...
void CreateShapes(const std::string &features)
Parse the features to create the shapes and set their options.
CPhyloNodeData & GetValue()
Return the value object for the node.
Definition: tree_model.hpp:159
bool HasParent() const
Check if the node has a parent.
Definition: tree_model.hpp:90
Definition: vect4.hpp:49
#define true
Definition: bool.h:35
static const char * str(char *buf, int n)
Definition: stats.c:84
static char tmp[3200]
Definition: utf8.c:42
string
Definition: cgiapp.hpp:687
#define NULL
Definition: ncbistd.hpp:225
#define NCBI_THROW(exception_class, err_code, message)
Generic macro to throw an exception, given the exception class, error code and message string.
Definition: ncbiexpt.hpp:704
float Length() const
Definition: vect2.hpp:271
T & X()
Definition: vect3.hpp:110
void Set(T x, T y)
Definition: vect2.hpp:260
T & X()
Definition: vect2.hpp:107
T & Y()
Definition: vect3.hpp:112
T & X()
Definition: vect4.hpp:111
T & Y()
Definition: vect4.hpp:113
T & Y()
Definition: vect2.hpp:109
static bool GetGIString(const string &sid, string *gi_str)
ad-hoc GI extraction (for misformed seq-id strings like: "gi|55823257|ref|YP_141698....
Definition: utils.cpp:2335
GLdouble TModelUnit
Definition: gltypes.hpp:48
void SetRight(T right)
Definition: glrect.hpp:114
void Color4fv(const GLfloat *v)
Definition: irender.hpp:98
T X() const
Definition: glpoint.hpp:59
T Height() const
Definition: glrect.hpp:90
virtual void Enable(GLenum glstate)=0
virtual void Begin(GLenum mode)=0
Start rendering.
void SetBottom(T bottom)
Definition: glrect.hpp:113
T Top() const
Definition: glrect.hpp:84
virtual void BlendFunc(GLenum sfactor, GLenum dfactor)=0
Options to be used when GL_BLEND is enabled.
T Bottom() const
Definition: glrect.hpp:82
T Width() const
Definition: glrect.hpp:86
TVPUnit ProjectX(TModelUnit m_x) const
Definition: glpane.cpp:661
IRender & GetGl()
convenience function for getting current render manager
void WriteText(TModelUnit x, TModelUnit y, const char *text, TModelUnit rotate_degrees=0.0) const
Write text at specified model coords.
void Vertex2d(GLdouble x, GLdouble y)
Definition: irender.hpp:185
T Right() const
Definition: glrect.hpp:83
TVPRect & GetViewport(void)
Definition: glpane.hpp:332
TVPUnit ProjectY(TModelUnit m_y) const
Definition: glpane.cpp:676
TModelUnit UnProjectX(TVPUnit m_x) const
Definition: glpane.cpp:706
T Left() const
Definition: glrect.hpp:81
T Y() const
Definition: glpoint.hpp:60
void BeginText() const
WriteText interface The WriteText functions produce the same results as TextOut but they are more eff...
virtual void End()=0
Finish rendering (create buffer and send to renderer)
virtual void PolygonMode(GLenum face, GLenum mode)=0
Set the polygon rasterization mode.
void EndText() const
Pops matrices and attributes after writing text.
virtual TModelUnit GetMetric(EMetric metric, const char *text=NULL, int len=-1) const
void SetLeft(T left)
Definition: glrect.hpp:112
virtual TModelUnit TextWidth(const char *text) const
Compute and return font metrics.
virtual void TextOut(const char *text) const
TextOut interface Write the specified text and set up state and transformation as needed.
void Vertex2f(GLfloat x, GLfloat y)
Definition: irender.hpp:182
TModelUnit GetScaleX(void) const
Definition: glpane.cpp:118
TModelUnit GetScaleY(void) const
Definition: glpane.cpp:123
void SetTop(T top)
Definition: glrect.hpp:115
string Truncate(const char *text, TModelUnit w, ETruncate trunc=eTruncate_Ellipsis) const
Truncate text to the secified width.
TVPPoint Project(TModelUnit m_x, TModelUnit m_y) const
Definition: glpane.cpp:691
CRgbaColor & GetColor(size_t i)
@ eMetric_CharHeight
Definition: glfont.hpp:76
const float * GetColorArray(void) const
Access the color array directly.
Definition: rgba_color.hpp:394
#define END_NCBI_SCOPE
End previously defined NCBI scope.
Definition: ncbistl.hpp:103
#define BEGIN_NCBI_SCOPE
Define ncbi namespace.
Definition: ncbistl.hpp:100
static string DoubleToString(double value, int precision=-1, TNumToStringFlags flags=0)
Convert double to string.
Definition: ncbistr.hpp:5187
static int StringToInt(const CTempString str, TStringToNumFlags flags=0, int base=10)
Convert string to int.
Definition: ncbistr.cpp:630
static list< string > & Split(const CTempString str, const CTempString delim, list< string > &arr, TSplitFlags flags=0, vector< SIZE_TYPE > *token_pos=NULL)
Split a string using specified delimiters.
Definition: ncbistr.cpp:3461
static double StringToDouble(const CTempStringEx str, TStringToNumFlags flags=0)
Convert string to double.
Definition: ncbistr.cpp:1387
static string IntToString(int value, TNumToStringFlags flags=0, int base=10)
Convert int to string.
Definition: ncbistr.hpp:5084
static string & ToLower(string &str)
Convert string to lower case – string& version.
Definition: ncbistr.cpp:405
@ fConvErr_NoThrow
Do not throw an exception on error.
Definition: ncbistr.hpp:285
unsigned int TBioTreeFeatureId
Feature Id.
Definition: bio_tree.hpp:60
void SetFeature(TBioTreeFeatureId id, const string &value)
Set feature value, feature if exists replaced, if not added.
Definition: bio_tree.cpp:56
TBioTreeFeatureId GetId(const string &feature_name) const
If feature is already registered returns its id by name.
Definition: bio_tree.cpp:209
TBioTreeFeatureId Register(const string &feature_name)
Register new feature, return its id.
Definition: bio_tree.cpp:160
const string & GetFeatureValue(TBioTreeFeatureId id) const
Get feature value by id.
Definition: bio_tree.cpp:69
bool HasFeature(const string &feature_name) const
Check if feature is listed in the dictionary.
Definition: bio_tree.cpp:146
void RemoveFeature(TBioTreeFeatureId id)
Remove feature from the list.
Definition: bio_tree.cpp:91
static const char label[]
n background color
int i
const struct ncbi::grid::netcache::search::fields::SIZE size
const GenericPointer< typename T::ValueType > T2 value
Definition: pointer.h:1227
#define abs(a)
Definition: ncbi_heapmgr.c:130
unsigned int a
Definition: ncbi_localip.c:102
EIPRangeType t
Definition: ncbi_localip.c:101
T max(T x_, T y_)
T min(T x_, T y_)
Int4 delta(size_t dimension_, const Int4 *score_)
double r(size_t dimension_, const Int4 *score_, const double *prob_, double theta_)
double f(double x_, const double &y_)
Definition: njn_root.hpp:188
#define PHYLO_EDGE_COLOR
#define EDGE_GRADIENT
#define PHYLO_NODE_MARKER
#define PHYLO_LABEL_BGCOLOR
#define PHYLO_NODE_COLLAPSED
#define PHYLO_NODE_SIZE
#define PHYLO_FEAT_CLUSTERID
#define PHYLO_LABEL_COLOR
#define PHYLO_FEAT_DIST
#define MAX_PROPERTIES
#define PHYLO_NODE_BOUNDED
#define PHYLO_FEAT_SEQID
#define PHYLO_NODE_COLOR
#define PHYLO_SELECT_CLUSTERS
#define PHYLO_FEAT_LABEL
vector< CRgbaColor > m_MarkerColors
CSubtreeBoundary * m_Boundary
SExtendedNodeParms & operator=(const SExtendedNodeParms &rhs)
vector< int > m_SelClusters
else result
Definition: token2.c:20
static const char *const features[]
Modified on Sun Apr 14 05:27:20 2024 by modify_doxy.py rev. 669887