zoukankan      html  css  js  c++  java
  • 一个用于显示数值曲线的类

      最近在做一个课题,要显示几条数值曲线。不过不想借助其它控件,或其它公司提供的开发包,如MATCOM,用这些的话就太简单不过了。下面是一个自己设计的一个类,用API堆的,这样既可以在基于SDK应用开发应用,又可以在MFC框架中应用。下面几个图是测试时截的。在此声明一下,我是一新手,难免设计的不合理甚至错误百出,敬请见谅!点此下载源代码和示例代码

     



    图1  显示多条曲线


     

    图2 显示坐标提示
    图3 坐标系显示范围缩放
     
         
    类名为CChart,其基类为CChartBase。CChartBase主要用于显示,设置坐标系的一些属性,比如x,y轴可以显示的范围、坐标系边框颜色、背景颜色等;而CChart则用于显示坐标系和多条曲线,曲线颜色、线宽、等凡是可见的属性都可以设定。用法如下:
     
    1. 将DispChart.h和DispChart.cpp包含至用使用该类的Project中,若为基于MFC项目,则在DispChart.cpp中添加#include ”stdafx.h”。
    2. 定义一个该类的变量,CChart chart(hWnd); hWnd是该坐标所在窗口的句柄。
    3. (可选)设置相应的属性。如:
       
                 chart.SetGridColor(RGB(255,0,0));    // 设置网格颜色
                  chart.SetGriddx(10);                 // 设置网格x轴间隔
                  chart.SetClrLabel(RGB(0,0,255));     // 标尺颜色
                  chart.SetXLabel("t/min");            // 轴标文字
                  chart.SetYLabel("V/v");
                  chart.SetRulerXFormat("%.2f");       // x轴标尺显示精度
                  chart.SetGriddy( 0.01);
                  chart.SetXRange( 0, 100);            // x轴可以显示的范围
                 chart.SetYRange( -5, 5); 
     
    4. 添加曲线数据连接,曲线数据必须是vector<double>型的。如:
          std::vector<double> data[3];
          int length = 1000;
       double amp = 5;
       for(int i=0;i<length;i++)
       {
        double t = (20 * 3.1415926 / length) * i;
        double y1 = amp*sin(t);
        double y2 = (amp/2)*cos(t);
        data[0].push_back(t);
        data[1].push_back(y1);
        data[2].push_back(y2);
       }
        chart.AddMCurves(data,3);
        chart.SetCurveColor(0,RGB(0,0,0));

     
    5. 在WM_PAINT消息或其它地方绘制曲线。先设置显示在那个位置,然后绘制。
        
    case WM_PAINT:
    		hdc = BeginPaint(hWnd, &ps);
    		// TODO: 在此添加任意绘图代码..
    		RECT rect;
    		GetClientRect(hWnd,&rect);
    
    		chart.SetChartDC(hdc);
     
    		chart.SetChartAndWindowPosition(rect);
    		
    		 chart.ShowCurves();
    
    		EndPaint(hWnd, &ps);
    		break;
     
    6. (可选)若要动态缩放、平移、左键点击显示坐标提示窗口、右键框选缩放,则只需在相应的消息处理处添加相关操作即可。注意:由于我是用该类绘制周期性的曲线的,所以平移和缩放只是x轴的;若要同时平移或缩放,在CChart::OnMouseWheel函数中将ScaleX改变为ScaleCenter即可以完成x,y轴同时缩放,在CChart::OnMouseMove函数中修改Move的第二参数为-(y - m_ptLeftButtonDown.y) * GetYPerPix()即可以完成x,y轴同时移动。
       if( m_ptLeftButtonDown.x != -1)
        {
     Move( -(x - m_ptLeftButtonDown.x) * GetXPerPix() , -(y - m_ptLeftButtonDown.y) * GetYPerPix());
        
     m_ptLeftButtonDown.x = x;
     m_ptLeftButtonDown.y = y;
     
    // 绘制曲线和坐标系
     ShowCurves();
     }
    示例代码:
    case WM_LBUTTONDOWN:
    		
    		chart.OnLeftButtonDown(LOWORD(lParam), HIWORD(lParam));
    		break;
    	case WM_LBUTTONUP:
    		chart.OnLeftButtonUp(LOWORD(lParam), HIWORD(lParam));
    		break;
    	case WM_RBUTTONDOWN:
    		chart.OnRightButtonDown(LOWORD(lParam), HIWORD(lParam));
    		break;
    	case WM_RBUTTONUP:
    		chart.OnRightButtonUp(LOWORD(lParam), HIWORD(lParam));
    		break;
    	case WM_MOUSEMOVE:
    		chart.OnMouseMove(LOWORD(lParam), HIWORD(lParam));
    		break;
    	case 0x020A/*WM_MOUSEWHEEL*/:
    		{
    			POINT pt = { LOWORD(lParam), HIWORD(lParam) };
    			ScreenToClient( hWnd,&pt );
    		    chart.OnMouseWheel(wParam, pt.x, pt.y);
    		}
    		break;
     
     
     头文件定义如下:
    #ifndef _DISPCHART_H
    #define _DISPCHART_H
    #include 
    #include 
    #include 
    
    // 图表基类:用于绘制坐标系和曲线
    class CChartBase
    {
    protected:
    	HDC       m_hChartDC;       // 图表绘制的DC
    	RECT      m_rtWindow;       // 坐标窗口,其中包含图表显示区和坐标标尺,轴标等    
    	RECT      m_rtChart;        // 图标显示区(依赖域m_rtWindow)
    
    	// 坐标显示边界
    	double    m_xStart;         // 实数域内x轴起点
    	double    m_xEnd;           //         x轴终点
    	double    m_yStart;         //         y轴起点
    	double    m_yEnd;           //         y轴终点
    
    	// 显示图表区
    	COLORREF  m_clrChartBg;     // 显示区背景色
    	COLORREF  m_clrChartBorder; //       边框色
    
    	// 网格
    	bool      m_bGridOn;        // 控制网格是否显示
    	double    m_dxGrid;         // 网格单元宽
    	double    m_dyGrid;         // 网格单元高
    	COLORREF  m_clrGrid;        // 网格线颜色
    
    	// 坐标轴,轴标,标尺
    	char      m_xLabel[20];
    	char      m_yLabel[20];
    	bool      m_bxLabelOn; 
    	bool      m_byLabelOn;
    
    	bool      m_bxRulerOn;
    	bool      m_byRulerOn;
    	char      m_szRulerXFormat[128];
    	char      m_szRulerYFormat[128];
    
    	COLORREF  m_clrLabel;      // 轴标文字和刻度文字颜色
    
    	// 文字字体
    	LOGFONT     m_logFont;
    
    	// 曲线数据
    
    public:
    
    	// 辅助函数
    	void SetChartDC(HDC hdc);
    	HDC  GetChartDC() const ;
    	void SetChartWindowPosition(RECT rect);
    	void SetChartWindowPosition(int left, int top, int right, int bottom);
    	RECT GetChartWindowPosition() const;
    	void SetChartPosition(RECT rect);
    	void SetChartPosition(int left, int top, int right, int bottom);
    
    	RECT GetChartPosition() const;
    	int  GetChartWidth()const  { return m_rtChart.right - m_rtChart.left ; };
    	int  GetChartHeight()const { return m_rtChart.bottom - m_rtChart.top ; };
    	int  GetChartWindowWidth() const { return m_rtWindow.right - m_rtWindow.left; };
    	int  GetChartWindowHeight() const{ return m_rtWindow.bottom - m_rtWindow.top; };
    
    	// 坐标显示边界
    	double SetXStart(double xStart);
    	double SetXEnd(double xEnd);
    	void   SetXRange(double xStart,double xEnd);
    	double SetYStart(double yStart);
    	double SetYEnd(double yEnd);
    	void   SetYRange(double yStart,double yEnd);
    	double GetXStart()const;
    	double GetXEnd()const;
    	double GetYStart()const;
    	double GetYEnd()const;
        
    	// 显示图表区
    	void      SetClrChartBg(COLORREF clr);
    	COLORREF  GetClrChartGb()const;
    	void      SetClrChartBorder(COLORREF clr);
    	COLORREF  GetClrChartBorder()const;
    
    	// 网格
    	double   SetGriddx(double dxGrid);              // 设置网格宽度,返回前一个值
    	double   SetGriddy(double dyGrid);              // 设置网格高度,返回前一个值
    	void     SetGridxy(double dxGrid,double dyGrid);
    	COLORREF SetGridColor(COLORREF color);          // 设置网格颜色,返回前一个值
    	void SetGridOn();                               // 设置网格为显示状态
    	void SetGridOff();                              // 设置网格为关闭状态
    
    	double   GetGriddx()const;
    	double   GetGriddy()const;
    	COLORREF GetGridColor()const;
    	bool     GetGridStatus()const;
    
    	// 坐标轴,轴标,标尺
    	void    SetXLabel(const char* xLabel);
    	void    SetYLabel(const char* yLabel);
    	void    SetXLabelOn();
    	void    SetXLabelOff();
    	BOOL    GetXLabelStatus()const;
    	void    SetYLabelOn();
    	void    SetYLabelOff();
    	BOOL    GetYLabelStatus()const;
    
    	void    SetXRulerOn();
    	void    SetXRulerOff();
    	BOOL    GetXRulerStatus()const;
    	void    SetYRulerOn();
    	void    SetYRulerOff();
    	BOOL    GetYRulerStatus()const;
    
    	void    SetRulerXFormat(const char str[]) { strcpy(m_szRulerXFormat, str);};
    	void    SetRulerYFormat(const char str[]) { strcpy(m_szRulerXFormat, str);};
    
    	void     SetClrLabel(COLORREF clr);
    	COLORREF GetClrLabel()const;
    
    	// 字体
    	void    SetLogFont(LOGFONT logFont);
    	LOGFONT GetLogFont()const;
    
    
    	// 每一个象素所代表的实数值
    	double GetYPerPix() const;
    	double GetXPerPix() const;
    
    protected:
    	int  ShowChartBg();
    	int  ShowGrid();
    	int  ShowRuler();
    	int  ShowLabel();
    
    public:
    	CChartBase();
    	~CChartBase();
    
    	int ShowAt(int left, int top, int right, int bottom); // 在rect中显示该图标窗口,外部最好用该函数
    	int ShowAt(RECT rect);
    	int Show();                                           // 通过设置各种参数显示
    
    	// 坐标转换 r--real  s--screen 2--to
    	int rx2sx(double rx);  
    	int ry2sy(double ry);
    	double sx2rx(int sx);
    	double sy2ry(int sy);
    
    	// 坐标变换
    	void Move(double drx, double dry);                   // 坐标系平移
    	void ScaleCenter(double times);                      // 坐标以坐标框的中心放缩
    	                                                     // times>1时,显示范围扩大,起到缩小的作用
    	                                                     // times<1时,显示范围缩小,起到放大的作用
    	void ScaleX(double times);                           // X轴范围缩放(以x轴中心)
    	void ScaleY(double times);                           // Y轴范围缩放(以y轴中心)
    };
    
    class CChart:public CChartBase
    {
    private:
    	HWND       m_hWnd;           // 图表所在的窗口,该窗口可以处理消息(用于实现坐标变换等)
    	HDC        m_memDCWindow;    // 存储整个绘图窗用的内存句柄
    	HBITMAP    m_bmpInDCWindow;  
    	HDC        m_memDCChart;     // 存储chart的内存设备句柄
        HBITMAP    m_bmpInDCChart;   // 图表所对应的位图句柄
    
    	// 曲线数据
    public:
    	
    	std::vector
  • 相关阅读:
    《构建之法》第四章学习笔记
    《深入理解计算机系统》第四章学习笔记
    《构建之法》第三章学习笔记
    《深入理解计算机系统》第三章学习笔记
    《文献管理与信息分析》第二讲学习笔记
    《深入理解计算机系统》第二章学习笔记
    20179223《Linux内核原理与分析》第十二周学习笔记
    《从问题到程序》第三章学习笔记
    51nod1256乘法逆元
    51nod1212无向图最小生成树
  • 原文地址:https://www.cnblogs.com/mywolrd/p/1930723.html
Copyright © 2011-2022 走看看