gldrawscale.cpp
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:11k
源码类别:

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: gldrawscale.cpp,v $
  4.  * PRODUCTION Revision 1000.2  2004/06/01 20:50:47  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.9
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: gldrawscale.cpp,v 1000.2 2004/06/01 20:50:47 gouriano Exp $
  10. * ===========================================================================
  11. *
  12. *                            PUBLIC DOMAIN NOTICE
  13. *               National Center for Biotechnology Information
  14. *
  15. *  This software/database is a "United States Government Work" under the
  16. *  terms of the United States Copyright Act.  It was written as part of
  17. *  the author's official duties as a United States Government employee and
  18. *  thus cannot be copyrighted.  This software/database is freely available
  19. *  to the public for use. The National Library of Medicine and the U.S.
  20. *  Government have not placed any restriction on its use or reproduction.
  21. *
  22. *  Although all reasonable efforts have been taken to ensure the accuracy
  23. *  and reliability of the software and data, the NLM and the U.S.
  24. *  Government do not and cannot warrant the performance or results that
  25. *  may be obtained by using this software or data. The NLM and the U.S.
  26. *  Government disclaim all warranties, express or implied, including
  27. *  warranties of performance, merchantability or fitness for any particular
  28. *  purpose.
  29. *
  30. *  Please cite the author in any work or product based on this material.
  31. *
  32. * ===========================================================================
  33. *
  34. * Author: Philip Johnson
  35. *
  36. * File Description: 'gldrawscale' -- contains class to nicely draw a scale
  37. * on screen (think sequence coordinates).
  38. *
  39. * ---------------------------------------------------------------------------
  40. */
  41. #include <ncbi_pch.hpp>
  42. #include <gui/opengl/gldrawscale.hpp>
  43. #include <gui/opengl/glfont.hpp>
  44. #include <corelib/ncbistre.hpp>
  45. #include <algorithm>
  46. #include <math.h>
  47. BEGIN_NCBI_SCOPE
  48. const char* CGlDrawScale::sm_SISymbols = "kMGTPEZY";
  49. //-----------------------------------------------------------------------------
  50. //PRE : font to use for drawing scale; whether or not to use abbreviations
  51. //when appropriate (and, if so, what sort to use)
  52. //POST: viewscale initialized
  53. CGlDrawScale::CGlDrawScale(IGlFont &font, EAbbrevType useAbbrev)
  54.     : m_Font(font),
  55.       m_UseAbbrev(useAbbrev),
  56.       m_CoordConverter(NULL)
  57. {
  58.     char tmp[2];
  59.     tmp[1] = '';
  60.     m_MaxDigitWidth = 0;
  61.     for(char d = '0'; d <= '9'; ++d) {
  62.         tmp[0] = d;
  63.         m_MaxDigitWidth = max(m_MaxDigitWidth, m_Font.TextWidth(tmp));
  64.     }
  65.     m_MaxSIPrefixWidth = 0;
  66.     for(unsigned int i = 0; sm_SISymbols[i] != ''; ++i) {
  67.         tmp[0] = sm_SISymbols[i];
  68.         m_MaxSIPrefixWidth = max(m_MaxSIPrefixWidth, m_Font.TextWidth(tmp));
  69.     }
  70. }
  71. //-----------------------------------------------------------------------------
  72. //PRE : unsigned integer (x)
  73. //POST: 10^n
  74. unsigned int CGlDrawScale::x_Exp10(unsigned int x) const
  75. {
  76.     unsigned int n;
  77.     n = 1;
  78.     for(unsigned int i = 0; i < x; ++i) {
  79.         n *= 10;
  80.     }
  81.     return n;
  82. }
  83. //-----------------------------------------------------------------------------
  84. //PRE : an integer
  85. //POST: if greater than 2 digits, integer rounded up to first number with
  86. //only 2 significant digits; if exactly 2 digits, integer rounded up to
  87. //first number with 1 significant digit; if between 5 and 10, rounded up to
  88. //10; if less than 5, rounded up to 5
  89. void CGlDrawScale::x_Normalize(int &num) const
  90. {
  91.     int sign = 1;
  92.     if (num < 0) { //remove negative
  93.         sign = -1;
  94.         num *= -1;
  95.     }
  96.     int digitsI = (num == 0) ? 1 : (int) floor(log10((float)num) + 1);
  97.     if (digitsI >= 3) {
  98.         num = (num / x_Exp10(digitsI-2) + 1) * x_Exp10(digitsI-2);
  99.     } else if (digitsI == 2) {
  100.         num = (num / x_Exp10(digitsI-1) + 1) * x_Exp10(digitsI-1);
  101.     } else if (num > 5) {
  102.         num = 10;
  103.     } else {
  104.         num = 5;
  105.     }
  106.     num *= sign; //put back negative (if had in originally)
  107. }
  108. //-----------------------------------------------------------------------------
  109. //PRE : a number
  110. //POST: a string representing that number
  111. string CGlDrawScale::x_GenerateLabel(int num, EAbbrevType type) const
  112. {
  113.     CNcbiOstrstream oss;
  114.     switch(type) {
  115.     case eNoAbbrev:
  116.         oss << num;
  117.         break;
  118.     case eCommas:
  119.         {
  120.             int count = 0;
  121.             while (abs(num) >= 10) {
  122.                 oss << num % 10;
  123.                 if (++count % 3 == 0) {
  124.                     oss << ',';
  125.                 }
  126.                 num /= 10;
  127.             }
  128.             oss << num % 10;
  129.             string tmp = CNcbiOstrstreamToString(oss);
  130.             reverse(tmp.begin(), tmp.end());
  131.             return tmp;
  132.         }
  133.     case eUseScientificNotation:
  134.         oss.precision(3);
  135.         oss.flags(oss.scientific);
  136.         oss << (float) num;
  137.         break;
  138.     case eUseSISymbols:
  139.         {{
  140.             int prefixI = -1;
  141.             float decimal = (float)num;
  142.             while (abs(num) >= 1000) {
  143.                 ++prefixI;
  144.                 decimal = (float) num / 1000;
  145.                 num /= 1000;
  146.             }
  147.             oss << decimal;
  148.             if (prefixI >= 0) {
  149.                 oss << sm_SISymbols[prefixI] << '';
  150.             }
  151.         }}
  152.         break;
  153.     }
  154.     return CNcbiOstrstreamToString(oss);
  155. }
  156. //-----------------------------------------------------------------------------
  157. //PRE : left-most user coordinate, right-most user coordinate
  158. //POST: maximum size of label for this range
  159. unsigned int CGlDrawScale::x_CalcMaxLabelSize(int left, int right,
  160.                                               EAbbrevType abbrev) const
  161. {
  162.     unsigned int size = 0;
  163.     int digitsL = (left == 0) ? 1 : (int) floor(log10((float)abs(left)) + 1);
  164.     int digitsR = (right == 0) ? 1 : (int) floor(log10((float)abs(right)) + 1);
  165.     switch (abbrev) {
  166.     case eNoAbbrev: //DDDDD..
  167.         size = (unsigned int)(max(digitsR, digitsL) * m_MaxDigitWidth);
  168.         break;
  169.     case eCommas: //D,DDD,DDD...
  170.         size =
  171.             (unsigned int)((max(digitsL, digitsR) + max(digitsL, digitsR) / 3)
  172.             * m_MaxDigitWidth);
  173.         break;
  174.     case eUseSISymbols: //DDD.DDDk
  175.         size = (unsigned int)(m_MaxDigitWidth * 6 + m_Font.TextWidth(".") +
  176.             m_MaxSIPrefixWidth);
  177.         break;
  178.     case eUseScientificNotation: //D.DDDe+DD
  179.         size = (unsigned int)(m_MaxDigitWidth * 6 + m_Font.TextWidth(".e+"));
  180.         break;
  181.     }
  182.     if (left < 0  ||  right < 0) {
  183.         size += (unsigned int)(m_Font.TextWidth("-"));
  184.     }
  185.     return size;
  186. }
  187. //-----------------------------------------------------------------------------
  188. //PRE : width in pixels; left-most user coordinate, right-most user
  189. //coordinate
  190. //POST: scale drawn in the following box: left, -0.5, right, [font-height]
  191. void CGlDrawScale::Draw(int width, int left, int right) const 
  192. {
  193.     if (width <= 0)
  194.         throw runtime_error("CGlDrawScale::Draw given non-positive width.");
  195.     double xScale, yScale;
  196.     {
  197.         GLint viewport[4];
  198.         GLdouble mvMatrix[16], projMatrix[16];
  199.         GLdouble wx1,wx2,wy1,wy2,wz; //world coordinates
  200.         glGetIntegerv(GL_VIEWPORT, viewport);
  201.         glGetDoublev(GL_MODELVIEW_MATRIX, mvMatrix);
  202.         glGetDoublev(GL_PROJECTION_MATRIX, projMatrix);
  203.         int glL = m_CoordConverter ? m_CoordConverter->ToGl(left) : left;
  204.         int glR = m_CoordConverter ? m_CoordConverter->ToGl(right) : right;
  205.         gluUnProject(glL,0,0, mvMatrix, projMatrix, viewport, &wx1,&wy1,&wz);
  206.         gluUnProject(glR,1,0, mvMatrix, projMatrix, viewport, &wx2,&wy2,&wz);
  207.         xScale = (wx2-wx1)/(glR-glL);
  208.         yScale = (wy2-wy1);
  209.     }
  210.     EAbbrevType abbrevType;
  211.     if (m_UseAbbrev != eNoAbbrev && //use abbreviations
  212.         abs(right-left) > width) { //big interval
  213.         abbrevType = m_UseAbbrev;
  214.     } else {
  215.         abbrevType = eNoAbbrev;
  216.     }
  217.     unsigned int maxLabelSize = x_CalcMaxLabelSize(left, right, abbrevType);
  218.     int labelInterval = (int) ceil(((float)(right-left) / width) *
  219.                                    (maxLabelSize*1.5));
  220.     x_Normalize(labelInterval);
  221.     int minBound = min(left, right);
  222.     int maxBound = max(left, right);
  223.     int labelStart = left;
  224.     if (labelStart % labelInterval != 0) {
  225.         labelStart = (labelStart / labelInterval) * labelInterval;
  226.         if (labelStart < minBound  ||  labelStart > maxBound) {
  227.             labelStart += labelInterval;
  228.         }
  229.     }
  230.     //labels
  231.     for (int labelPos = labelStart;
  232.          labelPos >= minBound  &&  labelPos <= maxBound;
  233.          labelPos += labelInterval) {
  234.         string label = x_GenerateLabel(labelPos, abbrevType);
  235.         m_Font.TextOut((m_CoordConverter ? m_CoordConverter->ToGl(labelPos) :
  236.                         labelPos) -
  237.                        (m_Font.TextWidth(label.c_str()) * xScale / 2),
  238.                        3.0f * yScale, label.c_str());
  239.     }
  240.     
  241.     //tickmarks
  242.     glBegin(GL_LINES);
  243.     int tickInterval = max(1, abs(labelInterval) / 5);
  244.     if (labelInterval < 0) {
  245.         tickInterval *= -1;
  246.     }
  247.     int tickStart = left;
  248.     if (tickStart % tickInterval != 0) {
  249.         tickStart = (tickStart / tickInterval) * tickInterval;
  250.         if (tickStart < minBound  ||  tickStart > maxBound) {
  251.             tickStart += tickInterval;
  252.         }
  253.     }
  254.     for (int labelPos = tickStart;
  255.          labelPos >= minBound  &&  labelPos <= maxBound;
  256.          labelPos += tickInterval) {
  257.         int glPos = (m_CoordConverter ? m_CoordConverter->ToGl(labelPos) :
  258.                      labelPos);
  259.         glVertex2f(glPos, (labelPos % labelInterval == 0) ?
  260.                    -yScale * 4.0f : -yScale * 2.0f);
  261.         glVertex2f(glPos, 0);
  262.     }
  263.     glEnd();
  264. }
  265. END_NCBI_SCOPE
  266. /*===========================================================================
  267. * $Log: gldrawscale.cpp,v $
  268. * Revision 1000.2  2004/06/01 20:50:47  gouriano
  269. * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.9
  270. *
  271. * Revision 1.9  2004/05/21 22:27:45  gorelenk
  272. * Added PCH ncbi_pch.hpp
  273. *
  274. * Revision 1.8  2004/05/03 13:03:15  dicuccio
  275. * Fixed compiler warnings on MSVC7
  276. *
  277. * Revision 1.7  2004/03/11 17:38:14  dicuccio
  278. * Fixed compiler warnings
  279. *
  280. * Revision 1.6  2003/08/18 19:23:27  dicuccio
  281. * Minor reformatting.  Changed CGlFont to IGlFont
  282. *
  283. * Revision 1.5  2003/08/11 19:24:57  johnson
  284. * removed 1:1 correspondence between user coordinates & open gl world
  285. * coordinates (via CCoordConverter class); allow lefthand user coordinate to
  286. * be greater than righthand user coordinate
  287. *
  288. * Revision 1.4  2003/07/23 21:43:01  johnson
  289. * fix to work properly with negative coordinates
  290. *
  291. * Revision 1.3  2003/07/01 20:25:21  johnson
  292. * more fixes for GCC-2.95
  293. *
  294. * Revision 1.2  2003/07/01 20:04:31  johnson
  295. * fixed portability issues w/ sstream & math.h
  296. *
  297. * Revision 1.1  2003/07/01 15:45:28  johnson
  298. * initial revision
  299. *
  300. * ===========================================================================*/