gldrawscale.cpp
来自「ncbi源码」· C++ 代码 · 共 339 行
CPP
339 行
/* * =========================================================================== * PRODUCTION $Log: gldrawscale.cpp,v $ * PRODUCTION Revision 1000.2 2004/06/01 20:50:47 gouriano * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.9 * PRODUCTION * =========================================================================== *//* $Id: gldrawscale.cpp,v 1000.2 2004/06/01 20:50:47 gouriano Exp $* ===========================================================================** PUBLIC DOMAIN NOTICE* National Center for Biotechnology Information** This software/database is a "United States Government Work" under the* terms of the United States Copyright Act. It was written as part of* the author's official duties as a United States Government employee and* thus cannot be copyrighted. This software/database is freely available* to the public for use. The National Library of Medicine and the U.S.* Government have not placed any restriction on its use or reproduction.** Although all reasonable efforts have been taken to ensure the accuracy* and reliability of the software and data, the NLM and the U.S.* Government do not and cannot warrant the performance or results that* may be obtained by using this software or data. The NLM and the U.S.* Government disclaim all warranties, express or implied, including* warranties of performance, merchantability or fitness for any particular* purpose.** Please cite the author in any work or product based on this material.** ===========================================================================** Author: Philip Johnson** File Description: 'gldrawscale' -- contains class to nicely draw a scale* on screen (think sequence coordinates).** ---------------------------------------------------------------------------*/#include <ncbi_pch.hpp>#include <gui/opengl/gldrawscale.hpp>#include <gui/opengl/glfont.hpp>#include <corelib/ncbistre.hpp>#include <algorithm>#include <math.h>BEGIN_NCBI_SCOPEconst char* CGlDrawScale::sm_SISymbols = "kMGTPEZY";//-----------------------------------------------------------------------------//PRE : font to use for drawing scale; whether or not to use abbreviations//when appropriate (and, if so, what sort to use)//POST: viewscale initializedCGlDrawScale::CGlDrawScale(IGlFont &font, EAbbrevType useAbbrev) : m_Font(font), m_UseAbbrev(useAbbrev), m_CoordConverter(NULL){ char tmp[2]; tmp[1] = '\0'; m_MaxDigitWidth = 0; for(char d = '0'; d <= '9'; ++d) { tmp[0] = d; m_MaxDigitWidth = max(m_MaxDigitWidth, m_Font.TextWidth(tmp)); } m_MaxSIPrefixWidth = 0; for(unsigned int i = 0; sm_SISymbols[i] != '\0'; ++i) { tmp[0] = sm_SISymbols[i]; m_MaxSIPrefixWidth = max(m_MaxSIPrefixWidth, m_Font.TextWidth(tmp)); }}//-----------------------------------------------------------------------------//PRE : unsigned integer (x)//POST: 10^nunsigned int CGlDrawScale::x_Exp10(unsigned int x) const{ unsigned int n; n = 1; for(unsigned int i = 0; i < x; ++i) { n *= 10; } return n;}//-----------------------------------------------------------------------------//PRE : an integer//POST: if greater than 2 digits, integer rounded up to first number with//only 2 significant digits; if exactly 2 digits, integer rounded up to//first number with 1 significant digit; if between 5 and 10, rounded up to//10; if less than 5, rounded up to 5void CGlDrawScale::x_Normalize(int &num) const{ int sign = 1; if (num < 0) { //remove negative sign = -1; num *= -1; } int digitsI = (num == 0) ? 1 : (int) floor(log10((float)num) + 1); if (digitsI >= 3) { num = (num / x_Exp10(digitsI-2) + 1) * x_Exp10(digitsI-2); } else if (digitsI == 2) { num = (num / x_Exp10(digitsI-1) + 1) * x_Exp10(digitsI-1); } else if (num > 5) { num = 10; } else { num = 5; } num *= sign; //put back negative (if had in originally)}//-----------------------------------------------------------------------------//PRE : a number//POST: a string representing that numberstring CGlDrawScale::x_GenerateLabel(int num, EAbbrevType type) const{ CNcbiOstrstream oss; switch(type) { case eNoAbbrev: oss << num; break; case eCommas: { int count = 0; while (abs(num) >= 10) { oss << num % 10; if (++count % 3 == 0) { oss << ','; } num /= 10; } oss << num % 10; string tmp = CNcbiOstrstreamToString(oss); reverse(tmp.begin(), tmp.end()); return tmp; } case eUseScientificNotation: oss.precision(3); oss.flags(oss.scientific); oss << (float) num; break; case eUseSISymbols: {{ int prefixI = -1; float decimal = (float)num; while (abs(num) >= 1000) { ++prefixI; decimal = (float) num / 1000; num /= 1000; } oss << decimal; if (prefixI >= 0) { oss << sm_SISymbols[prefixI] << '\0'; } }} break; } return CNcbiOstrstreamToString(oss);}//-----------------------------------------------------------------------------//PRE : left-most user coordinate, right-most user coordinate//POST: maximum size of label for this rangeunsigned int CGlDrawScale::x_CalcMaxLabelSize(int left, int right, EAbbrevType abbrev) const{ unsigned int size = 0; int digitsL = (left == 0) ? 1 : (int) floor(log10((float)abs(left)) + 1); int digitsR = (right == 0) ? 1 : (int) floor(log10((float)abs(right)) + 1); switch (abbrev) { case eNoAbbrev: //DDDDD.. size = (unsigned int)(max(digitsR, digitsL) * m_MaxDigitWidth); break; case eCommas: //D,DDD,DDD... size = (unsigned int)((max(digitsL, digitsR) + max(digitsL, digitsR) / 3) * m_MaxDigitWidth); break; case eUseSISymbols: //DDD.DDDk size = (unsigned int)(m_MaxDigitWidth * 6 + m_Font.TextWidth(".") + m_MaxSIPrefixWidth); break; case eUseScientificNotation: //D.DDDe+DD size = (unsigned int)(m_MaxDigitWidth * 6 + m_Font.TextWidth(".e+")); break; } if (left < 0 || right < 0) { size += (unsigned int)(m_Font.TextWidth("-")); } return size;}//-----------------------------------------------------------------------------//PRE : width in pixels; left-most user coordinate, right-most user//coordinate//POST: scale drawn in the following box: left, -0.5, right, [font-height]void CGlDrawScale::Draw(int width, int left, int right) const { if (width <= 0) throw runtime_error("CGlDrawScale::Draw given non-positive width."); double xScale, yScale; { GLint viewport[4]; GLdouble mvMatrix[16], projMatrix[16]; GLdouble wx1,wx2,wy1,wy2,wz; //world coordinates glGetIntegerv(GL_VIEWPORT, viewport); glGetDoublev(GL_MODELVIEW_MATRIX, mvMatrix); glGetDoublev(GL_PROJECTION_MATRIX, projMatrix); int glL = m_CoordConverter ? m_CoordConverter->ToGl(left) : left; int glR = m_CoordConverter ? m_CoordConverter->ToGl(right) : right; gluUnProject(glL,0,0, mvMatrix, projMatrix, viewport, &wx1,&wy1,&wz); gluUnProject(glR,1,0, mvMatrix, projMatrix, viewport, &wx2,&wy2,&wz); xScale = (wx2-wx1)/(glR-glL); yScale = (wy2-wy1); } EAbbrevType abbrevType; if (m_UseAbbrev != eNoAbbrev && //use abbreviations abs(right-left) > width) { //big interval abbrevType = m_UseAbbrev; } else { abbrevType = eNoAbbrev; } unsigned int maxLabelSize = x_CalcMaxLabelSize(left, right, abbrevType); int labelInterval = (int) ceil(((float)(right-left) / width) * (maxLabelSize*1.5)); x_Normalize(labelInterval); int minBound = min(left, right); int maxBound = max(left, right); int labelStart = left; if (labelStart % labelInterval != 0) { labelStart = (labelStart / labelInterval) * labelInterval; if (labelStart < minBound || labelStart > maxBound) { labelStart += labelInterval; } } //labels for (int labelPos = labelStart; labelPos >= minBound && labelPos <= maxBound; labelPos += labelInterval) { string label = x_GenerateLabel(labelPos, abbrevType); m_Font.TextOut((m_CoordConverter ? m_CoordConverter->ToGl(labelPos) : labelPos) - (m_Font.TextWidth(label.c_str()) * xScale / 2), 3.0f * yScale, label.c_str()); } //tickmarks glBegin(GL_LINES); int tickInterval = max(1, abs(labelInterval) / 5); if (labelInterval < 0) { tickInterval *= -1; } int tickStart = left; if (tickStart % tickInterval != 0) { tickStart = (tickStart / tickInterval) * tickInterval; if (tickStart < minBound || tickStart > maxBound) { tickStart += tickInterval; } } for (int labelPos = tickStart; labelPos >= minBound && labelPos <= maxBound; labelPos += tickInterval) { int glPos = (m_CoordConverter ? m_CoordConverter->ToGl(labelPos) : labelPos); glVertex2f(glPos, (labelPos % labelInterval == 0) ? -yScale * 4.0f : -yScale * 2.0f); glVertex2f(glPos, 0); } glEnd();}END_NCBI_SCOPE/*===========================================================================* $Log: gldrawscale.cpp,v $* Revision 1000.2 2004/06/01 20:50:47 gouriano* PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.9** Revision 1.9 2004/05/21 22:27:45 gorelenk* Added PCH ncbi_pch.hpp** Revision 1.8 2004/05/03 13:03:15 dicuccio* Fixed compiler warnings on MSVC7** Revision 1.7 2004/03/11 17:38:14 dicuccio* Fixed compiler warnings** Revision 1.6 2003/08/18 19:23:27 dicuccio* Minor reformatting. Changed CGlFont to IGlFont** Revision 1.5 2003/08/11 19:24:57 johnson* removed 1:1 correspondence between user coordinates & open gl world* coordinates (via CCoordConverter class); allow lefthand user coordinate to* be greater than righthand user coordinate** Revision 1.4 2003/07/23 21:43:01 johnson* fix to work properly with negative coordinates** Revision 1.3 2003/07/01 20:25:21 johnson* more fixes for GCC-2.95** Revision 1.2 2003/07/01 20:04:31 johnson* fixed portability issues w/ sstream & math.h** Revision 1.1 2003/07/01 15:45:28 johnson* initial revision** ===========================================================================*/
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?