前文已经详细介绍了通用曲线控件源码定制开发从需求到编码实现,具体可参阅 通用曲线控件源码定制之设计实现篇 和 通用曲线控件定制之重点难点篇(附源码),本文由浮云E绘图开启大项目多曲线海量数据的曲线组件分析和实现之路。
一、需求背景
在一些工业控制领域,有大量设备采集多种类型的大量数据,需要可视化直观对比某时段/刻,同一设备上的各种数据状态,或者多个设备上的同一种数据,并且海量数据(数百万个点)高性能展示,现有市面上没有一款软件能做到精细化并高效的支持,需要专业团队定制研发一款适合大项目多曲线大数据量的曲线组件。
二、详细需求
本曲线组件功能需要主要包括:普通曲线功能、移动测量、多类型曲线、曲线组管理、业务支持和性能要求,具体描述如下表所示:
普通功能 | 标题 | 标题文字、字体大小、字颜色、背景色、位置等 |
脚注 | 脚注文字、字体大小、字颜色、背景色、位置等 | |
图例 | 图例名称、图例曲线颜色、风格、粗细等,图例隐藏显示 | |
X轴 | X轴是时间,刻度轴、刻度值、轴名称; 支持年月日时分秒毫秒微妙格式化缩放 |
|
Y轴 | Y轴是时间,刻度轴、刻度值、轴名称; 支持固定设置轴范围和自动计算轴范围 |
|
网格 | 网格线粗细、线性、颜色等 | |
曲线 | 曲线粗细、颜色、风格、标注等,具体看多类型曲线 | |
缩放 | 放大/缩小曲线区域,对应X轴刻度缩放 | |
移动翻页 | 左右移动翻页 | |
导出、打印 | 曲线导出成图片,可打印 | |
移动测量 | 鼠标移动实时画十字线 | 鼠标移动画异或十字线 |
透明信息提示框 | 透明度、边框、显示位置、显示文本和字体颜色等 | |
鼠标移动实时数值显示 | 鼠标点捕获计算实时坐标值,并在提示框显示 | |
多类型曲线 | 状态量曲线 | 即有限取值范围的曲线,比如红灯、黄灯、白灯、灭灯 |
模拟量曲线 | 即Y值是数值的曲线,比如电压200伏 | |
曲线组管理 | 添加、删除多子曲线 | 可一屏展示多区域曲线,比如某采集设备的4条曲线分4个区域展示 |
多子曲线同步移动、缩放等 | 基于相同X时间轴,同步移动缩放所有子曲线 | |
子曲线折叠/展开 | 为了充分理由曲线区域,支持子曲线纵向折叠和展开 | |
业务支持 | 年、月统计曲线 | 支持统计曲线,并标注 |
日曲线 | 支持历史点曲线,一屏展示设备属性的一整天所有点 | |
实时播放曲线 | 曲线支持动态实时播放,比如实时曲线 | |
曲线播放 | 支持曲线回放时,按时间有序动态播放曲线 | |
性能要求 | 支持海量数据点高效绘制 | 支持10条子曲线、200万以上个数据点的0.5s以内绘制 |
三、技术要求
要求把本曲线模块封装成功能独立的DLL,以供第三方项目跨语言支持。本曲线组件功能非常丰富,相关类很多、类的属性很多、类的方法很多,所以提供给第三方的接口非常多,为了更有模块化和清晰的接口结构,请不要用函数导出(C#和VC++调用dll步骤,接口指针、字符串等类型对应关系)方式提供接口,以类导出的方式提供接口,采用C++/CLI技术实现。
浮云E绘图已经完整实现了上述所有功能,满足所有功能要求、性能要求和技术要求,并已经成功应用于多个大项目上。有需要定制开发源码,请联系。
1 //作者:浮云E绘图,专业定制CAD等绘图工具、工控曲线、报表等软件 2 //QQ:316868127 3 void CChartView::OnPaint() 4 { 5 CPaintDC outputdc(this); 6 7 CRect rect; 8 GetClientRect(&rect); 9 10 SCROLLINFO sih; 11 sih.cbSize = sizeof(SCROLLINFO); 12 sih.fMask = SIF_POS; 13 SCROLLINFO siv; 14 siv.cbSize = sizeof(SCROLLINFO); 15 siv.fMask = SIF_POS; 16 if (!GetScrollInfo(SB_HORZ, &sih)) 17 sih.nPos = 0; 18 if (!GetScrollInfo(SB_VERT, &siv)) 19 siv.nPos = 0; 20 21 CRect totalRect; 22 int virtheight = m_virtualHeight + 1; 23 totalRect.SetRect(0, 0, rect.Width(), virtheight); 24 25 // Creating memory CDC 26 CDC dc; 27 dc.CreateCompatibleDC(&outputdc); 28 CBitmap bmp; 29 bmp.CreateCompatibleBitmap(&outputdc, rect.right, rect.bottom); 30 CBitmap* oldbmp = dc.SelectObject(&bmp); 31 32 33 dc.SetWindowOrg(sih.nPos, siv.nPos); 34 35 Draw(&dc, totalRect); 36 37 // Blit the memory CDC to screen 38 outputdc.BitBlt(0, 0, rect.right, rect.bottom, &dc, sih.nPos, siv.nPos, SRCCOPY); 39 //sih.nPos->0, siv.nPos->0 40 dc.SelectObject(oldbmp); 41 }