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

Go to the SVN repository for this file.

1 /* $Id: axis.cpp 27503 2013-02-26 18:16:55Z falkrb $
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: Andrey Yazhuk
27  *
28  * File Description:
29  *
30  */
31 
32 #include <ncbi_pch.hpp>
33 #include <gui/graph/axis.hpp>
34 #include <gui/opengl/glutils.hpp>
35 
36 #include <math.h>
37 #include <stdio.h>
38 
40 
41 ////////////////////////////////////////////////////////////////////////////////
42 /// class CAxisRenderer
43 
44 const int CAxisRenderer::kDefTickSize = 5;
45 
47 : m_bHorz(bHorz),
48  m_Type(eDec),
49  m_PosType(ePosMin),
50  m_FixedPosValue(0),
51  m_TextAlignType(eLeftText),
52  m_sFormatTempl("%g"),
53  m_TickStyle(eBothSides), m_TickSize(kDefTickSize),
54  m_Color(0.0f, 0.0f, 0.2f),
55  m_TextColor(0.5f, 0.5f, 0.5f),
56  m_Font(CGlBitmapFont::eHelvetica12)
57 {
58 }
59 
61 {
62 }
63 
65 {
66  m_bHorz = bHorz;
67 }
69 {
70  m_PosType = Type;
71 }
72 
74 {
76 }
77 
79 {
81 }
82 
83 // function tales sTempl that is a printf-style temaplate for formatting a value of
84 // TModelUnit type
85 void CAxisRenderer::SetFormattingTemplate(const string& sTempl)
86 {
87  m_sFormatTempl = sTempl;
88 }
89 
90 /*###void CAxisRenderer::SetFont(CGlBitmapFont::EFont Type)
91 {
92  m_Font = CGlBitmapFont(Type);
93 }*/
94 
96 {
98 }
99 
100 void CAxisRenderer::SetTickSize(int SizePix)
101 {
102  m_TickSize = SizePix;
103 }
104 
106 {
107  m_Type = Type;
108 }
109 
111 {
112  m_Color = Color;
113 }
114 
116 {
117  m_TextColor = Color;
118 }
119 
120 void CAxisRenderer::Render(CGlPane* pAreaPane, CGlPane* pGraphPane, CRegularGridGen* pGen)
121 {
122  // in order for CGlPane::Project() to work we need to initilize pane
123  pGraphPane->OpenOrtho();
124  pGraphPane->Close();
125 
126  TVPRect rcVP = pAreaPane->GetViewport();
127  TVPRect rcGraphVP = pGraphPane->GetViewport();
128 
129  // now drawing
130  pAreaPane->OpenPixels();
131 
132  pGen->GenerateGrid(pGraphPane, m_bHorz);
133  x_GenerateLabels(pAreaPane, pGraphPane, pGen);
134 
135  glLineWidth(0.1f);
136 
137  int dTickMin = (m_TickStyle == eMinSide || m_TickStyle == eBothSides) ? -m_TickSize : 0;
138  int dTickMax = (m_TickStyle == eMaxSide || m_TickStyle == eBothSides) ? m_TickSize : 0;
139 
140  if(m_bHorz) {
141  x_DrawHorzLabels(pAreaPane, pGraphPane, pGen, dTickMin, dTickMax);
142  } else {
143  int vpX = 0;
144  switch(m_PosType) {
145  case ePosMin: vpX = rcGraphVP.Left(); break;
146  case ePosMax: vpX = rcGraphVP.Right(); break;
147  case ePosFixedValue: vpX = pGraphPane->ProjectX(m_FixedPosValue); break;
148  }
149 
150  glColorC(m_Color);
151  glBegin(GL_LINES);
152  // draw axis
153  double vpBottom = rcGraphVP.Bottom();
154  double vpTop = rcGraphVP.Top();
155 
156  glVertex2d(vpX, vpBottom);
157  glVertex2d(vpX, vpTop);
158 
159  if (m_TickStyle != eNoTick) {
160  // draw Ticks
161  ITERATE(CRegularGridGen, it, *pGen) {
162  double wY = *it;
163  int vpY = pGraphPane->ProjectY(wY);
164  if(vpY >= vpBottom && vpY <= vpTop)
165  {
166  glVertex2d(vpX + dTickMin, vpY);
167  glVertex2d(vpX + dTickMax, vpY);
168  }
169  }
170  }
171  glEnd();
172 
173  // drawing Labels
174  x_LayoutLabels(rcVP.Bottom(), rcVP.Top());
176  int H = (int)m_Font.TextHeight();
177  ITERATE(vector<SLabelDescr>, itL, m_vLabels) {
178  if (itL->m_bVisible) {
179  int tX = vpX;
180 
181  switch (m_TextAlignType) {
182  case eLeftText: tX +=10; break;
183  case eRightText: tX -= 10 + itL->m_Width; break;
184  case eCenterText: tX -= itL->m_Width / 2; break;
185  }
186  int tY = itL->m_Pos - H/2;
187  m_Font.TextOut(tX, tY, itL->m_Str.c_str());
188  }
189  }
190  }
191 
192  pAreaPane->Close();
193 }
194 
195 void CAxisRenderer::x_DrawHorzLabels(CGlPane* pAreaPane, CGlPane* pGraphPane, CRegularGridGen* pGen, int dTickMin, int dTickMax)
196 {
197  TVPRect rcVP = pAreaPane->GetViewport();
198  TVPRect rcGraphVP = pGraphPane->GetViewport();
199 
200  int vpY = 0;
201  switch(m_PosType) {
202  case ePosMin: vpY = rcGraphVP.Bottom(); break;
203  case ePosMax: vpY = rcGraphVP.Top(); break;
204  case ePosFixedValue: vpY = pGraphPane->ProjectY(m_FixedPosValue); break;
205  }
206  glColorC(m_Color);
207  glBegin(GL_LINES);
208 
209  // draw axis
210  int vpLeft = pGraphPane->GetViewport().Left();
211  int vpRight = pGraphPane->GetViewport().Right();
212 
213  glVertex2d(vpLeft, vpY);
214  glVertex2d(vpRight, vpY);
215 
216  if (m_TickStyle != eNoTick) {
217  // draw Ticks
218  ITERATE(CRegularGridGen, it, *pGen) {
219  double wX = *it;
220  int vpX = pGraphPane->ProjectX(wX);
221  if(vpX >= vpLeft && vpX <= vpRight)
222  {
223  glVertex2d(vpX, vpY + dTickMin);
224  glVertex2d(vpX, vpY + dTickMax);
225  }
226  }
227  }
228  glEnd();
229 
230  // drawing Labels
231  x_LayoutLabels(rcVP.Left(), rcVP.Right());
233  int tY = vpY - 10 - (int) m_Font.TextHeight();
234  ITERATE(vector<SLabelDescr>, itL, m_vLabels) {
235  if (itL->m_bVisible) {
236  int tX = itL->m_Pos;
237 
238  switch (m_TextAlignType) {
239  case eLeftText: break;
240  case eRightText: tX -= itL->m_Width; break;
241  case eCenterText: tX -= itL->m_Width / 2; break;
242  }
243 
244  m_Font.TextOut(tX, tY, itL->m_Str.c_str());
245  }
246  }
247 }
249 {
250  m_vLabels.resize(0);
251  int vpZ, vpStart, vpFinish;
252  ITERATE(CRegularGridGen, it, *pGen) {
253  if(m_bHorz) {
254  vpZ = pGraphPane->ProjectX(*it);
255  vpStart = pGraphPane->GetViewport().Left();
256  vpFinish = pGraphPane->GetViewport().Right();
257  } else {
258  vpZ = pGraphPane->ProjectY(*it);
259  vpStart = pGraphPane->GetViewport().Bottom();
260  vpFinish = pGraphPane->GetViewport().Top();
261  }
262 
263  if(vpZ >= vpStart && vpZ <= vpFinish)
264  {
265  SLabelDescr Label;
266  Label.m_Value = *it;
267  Label.m_Pos = vpZ;
268  TModelUnit V = x_GetLabelValue(*it);
269  Label.m_Str = x_FormatLabel(V);
270  Label.m_Width = (int)m_Font.TextWidth(Label.m_Str.c_str());
271  m_vLabels.push_back(Label);
272  }
273  }
274 }
275 
276 #define LABEL_SPACE_X 8
277 #define LABEL_SPACE_Y 1
278 
279 void CAxisRenderer::x_LayoutLabels(int Start, int Finish)
280 {
281  int Min = Start;
282  int Max = Finish;
283  int Space = m_bHorz ? LABEL_SPACE_X : LABEL_SPACE_Y;
284  int H = (int)m_Font.TextHeight();
285 
286  NON_CONST_ITERATE(vector<SLabelDescr>, it, m_vLabels) {
287  int Size = m_bHorz ? it->m_Width : H;
288  int LabelMin = it->m_Pos - Size / 2;
289  int LabelMax = LabelMin + Size + Space;
290 
291  if (LabelMin < Min || LabelMax > Max)
292  it->m_bVisible = false;
293  else {
294  it->m_bVisible = true;
295  Min = LabelMax + 1;
296  }
297  }
298 }
299 
300 
302 {
303  char S[200];
304  sprintf(S, m_sFormatTempl.c_str(), Value);
305  return S;
306 }
307 
309 {
310  switch(m_Type) {
311  case eLog2:
312  return pow(TModelUnit(2.0), Value);
313  case eLog10:
314  return pow(TModelUnit(10.0), Value);
315  case eLn:
316  return exp(Value);
317  case eDec:
318  return Value;
319  default:
320  _ASSERT(false);
321  return -1;
322  }
323 }
324 
325 ////////////////////////////////////////////////////////////////////////////////
326 /// class CAxisArea
327 
329 : m_BoundsColor(0.5f, 0.5f, 0.5f)
330 {
331 }
332 
333 
335 {
336 }
337 
338 //override this functions in order to customize axes
340 {
341  static const int kDefTickSize = 4;
342 
343  m_XAxis.SetHorizontal(true);
344  m_XAxis.SetTickSize(kDefTickSize);
347 
348  m_YAxis.SetHorizontal(false);
349  m_YAxis.SetTickSize(kDefTickSize);
352 }
353 
355 {
356  m_XAxis.SetScaleType(TypeX);
357  m_YAxis.SetScaleType(TypeY);
358 }
359 
360 void CAxisArea::Render(CGlPane* pAreaPane, CGlPane* pGraphPane, CRegularGridGen* pGen)
361 {
362  //drawing bounding rectangle
363  /*pAreaPane->OpenPixels();
364 
365  TVPRect rcGraphVP = pGraphPane->GetViewport();
366 
367  glColorC(m_BoundsColor);
368  glPolygonMode(GL_FRONT, GL_LINE);
369  glRectd(rcGraphVP.Left(), rcGraphVP.Bottom(), rcGraphVP.Right(), rcGraphVP.Top());
370 
371  pAreaPane->Close(); */
372 
373  // drawing Axes
374  m_XAxis.Render(pAreaPane, pGraphPane, pGen);
375  m_YAxis.Render(pAreaPane, pGraphPane, pGen);
376 }
377 
#define LABEL_SPACE_X
Definition: axis.cpp:276
#define LABEL_SPACE_Y
Definition: axis.cpp:277
class CGlPane
Definition: glpane.hpp:62
CRegularGridGen.
class CRgbaColor provides a simple abstraction for managing colors.
Definition: rgba_color.hpp:58
Definition: svg.hpp:122
Definition: svg.hpp:543
#define H(x, y, z)
Definition: md4.c:180
#define ITERATE(Type, Var, Cont)
ITERATE macro to sequence through container elements.
Definition: ncbimisc.hpp:815
#define NON_CONST_ITERATE(Type, Var, Cont)
Non constant version of ITERATE macro.
Definition: ncbimisc.hpp:822
void SetColor(CRgbaColor Color)
Definition: axis.cpp:110
void SetTextColor(CRgbaColor Color)
Definition: axis.cpp:115
void SetTextAlign(ETextAlign Type)
Definition: axis.cpp:78
virtual void SetupAxes()
Definition: axis.cpp:339
void SetTickSize(int SizePix)
Definition: axis.cpp:100
TModelUnit m_FixedPosValue
Definition: axis.hpp:132
virtual TModelUnit x_GetLabelValue(TModelUnit Value)
Definition: axis.cpp:308
CAxisRenderer(bool bHorz=true)
Definition: axis.cpp:46
EScaleType m_Type
Definition: axis.hpp:129
vector< SLabelDescr > m_vLabels
Definition: axis.hpp:145
CAxisRenderer m_XAxis
Definition: axis.hpp:165
string m_sFormatTempl
Definition: axis.hpp:135
virtual void x_LayoutLabels(int Start, int Finish)
Definition: axis.cpp:279
virtual void x_GenerateLabels(CGlPane *pAreaPane, CGlPane *pGraphPane, CRegularGridGen *pGen)
Definition: axis.cpp:248
virtual ~CAxisRenderer()
Definition: axis.cpp:60
ETextAlign m_TextAlignType
Definition: axis.hpp:134
CRgbaColor m_TextColor
Definition: axis.hpp:141
void SetFixedPosition(TModelUnit Value)
Definition: axis.cpp:73
bool m_bHorz
Definition: axis.hpp:128
CGlBitmapFont m_Font
Definition: axis.hpp:143
void Render(CGlPane *pAreaPane, CGlPane *pGraphPane, CRegularGridGen *pGen)
Definition: axis.cpp:360
void SetScaleType(EScaleType TypeX, EScaleType TypeY)
Definition: axis.cpp:354
CRgbaColor m_Color
Definition: axis.hpp:140
static const int kDefTickSize
class CAxisRenderer
Definition: axis.hpp:126
CAxisArea()
class CAxisArea
Definition: axis.cpp:328
virtual ~CAxisArea()
Definition: axis.cpp:334
CAxisRenderer m_YAxis
Definition: axis.hpp:166
virtual void x_DrawHorzLabels(CGlPane *pAreaPane, CGlPane *pGraphPane, CRegularGridGen *pGen, int dTickMin, int dTickMax)
Definition: axis.cpp:195
int m_TickSize
Definition: axis.hpp:138
ETickStyle m_TickStyle
Definition: axis.hpp:137
void GenerateGrid(CGlPane *pPane, bool bHorz)
iteration interface.
EPosition m_PosType
Definition: axis.hpp:131
virtual string x_FormatLabel(TModelUnit Value)
Definition: axis.cpp:301
void SetPositionType(EPosition Type)
Definition: axis.cpp:68
void SetTickStyle(ETickStyle Style)
Definition: axis.cpp:95
void SetHorizontal(bool bHorz=true)
Definition: axis.cpp:64
void SetFormattingTemplate(const string &sTempl)
Definition: axis.cpp:85
virtual void Render(CGlPane *pAreaPane, CGlPane *pGraphPane, CRegularGridGen *pGen)
Definition: axis.cpp:120
void SetScaleType(EScaleType Type)
Definition: axis.cpp:105
@ ePosFixedValue
Definition: axis.hpp:60
@ eBothSides
Definition: axis.hpp:73
@ eRightText
Definition: axis.hpp:65
@ eCenterText
Definition: axis.hpp:66
GLdouble TModelUnit
Definition: gltypes.hpp:48
bool OpenOrtho()
Definition: glpane.hpp:427
virtual void TextOut(const char *text) const
T Top() const
Definition: glrect.hpp:84
T Bottom() const
Definition: glrect.hpp:82
bool OpenPixels()
Definition: glpane.hpp:432
TVPUnit ProjectX(TModelUnit m_x) const
Definition: glpane.cpp:661
T Right() const
Definition: glrect.hpp:83
TVPRect & GetViewport(void)
Definition: glpane.hpp:332
TVPUnit ProjectY(TModelUnit m_y) const
Definition: glpane.cpp:676
virtual TModelUnit TextHeight(void) const
compute the height of a string
virtual TModelUnit TextWidth(const char *text) const
compute the length of a null-terminated string
EScaleType
Definition: glpane.hpp:47
T Left() const
Definition: glrect.hpp:81
void glColorC(const CRgbaColor &color)
Definition: glutils.hpp:177
void Close(void)
Definition: glpane.cpp:178
@ eLn
Definition: glpane.hpp:51
@ eLog10
Definition: glpane.hpp:49
@ eDec
Definition: glpane.hpp:48
@ eLog2
Definition: glpane.hpp:50
#define END_NCBI_SCOPE
End previously defined NCBI scope.
Definition: ncbistl.hpp:103
#define BEGIN_NCBI_SCOPE
Define ncbi namespace.
Definition: ncbistl.hpp:100
unsigned int
A callback function used to compare two keys in a database.
Definition: types.hpp:1210
#define S(x, n)
GenericValue< UTF8<> > Value
GenericValue with UTF8 encoding.
Definition: document.h:2107
#define _ASSERT
#define Type
Modified on Sat Dec 09 04:49:53 2023 by modify_doxy.py rev. 669887