65.9K
CodeProject 正在变化。 阅读更多。
Home

用于图形绘制的简单 C# 库

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.90/5 (246投票s)

2009 年 1 月 25 日

CPOL

2分钟阅读

viewsIcon

1002209

downloadIcon

87048

一个用于快速简单绘制图表的 C# 库。

引言

在我们的应用程序中,我们必须显示一个多通道心电图 (ECG) 设备的输出。我查看了一些商业库,但它们都不能满足我的需求。因此,我决定自己设计一个简单的解决方案。

这是我尝试设计一个灵活、易于使用的绘图库。

该库能够以不同的布局显示多个图表。目前,可以显示五种模式

  • Normal: 表示所有数据源显示在一个图表窗口中,带有单独的纵坐标。
  • Stacked: 表示所有数据源显示在一个图表窗口中,垂直堆叠,共享纵坐标和横坐标。
  • 垂直对齐:表示图表窗口垂直对齐显示,带有单独的纵坐标和共享的横坐标。
  • 平铺水平:表示数据源在平铺窗口中显示(首选对齐方向为水平)。
  • 平铺垂直:表示数据源在平铺窗口中显示(首选对齐方向为垂直)。

图表可以未缩放或自动缩放显示。在自动缩放模式下,可见图表将自动适应可见区域。

以下图像显示了不同显示模式的示例

正常

GraphPlotting/graph_normal.png

堆叠

GraphPlotting/graph_stacked.png

水平平铺

GraphPlotting/graph_tiled_horizontal.png

垂直平铺

GraphPlotting/graph_tiled_vertically.png

垂直对齐

GraphPlotting/graph_vertically_aligned.png

X轴自动缩放

GraphPlotting/graph_fixed_x_range.png

以下图像显示了一个心电图应用程序的示例,其中八个数据源垂直平铺并自动缩放显示。

GraphPlotting/sample_2.jpg

Using the Code

该控件非常简单易用。只需查看示例应用程序即可。以下代码显示了演示应用程序中生成不同示例图表的部分

        protected void CalcDataGraphs()
        {

            this.SuspendLayout();
           
            display.DataSources.Clear();
            display.SetDisplayRangeX(0, 400);

            for (int j = 0; j < NumGraphs; j++)
            {
                display.DataSources.Add(new DataSource());
                display.DataSources[j].Name = "Graph " + (j + 1);                
                display.DataSources[j].OnRenderXAxisLabel += RenderXLabel;
              
                switch (CurExample)
                {
                    case  "NORMAL":
                        this.Text = "Normal Graph";
                        display.DataSources[j].Length = 5800;
                        display.PanelLayout = PlotterGraphPaneEx.LayoutMode.NORMAL;
                        display.DataSources[j].AutoScaleY = false;
                        display.DataSources[j].SetDisplayRangeY(-300, 300);
                        display.DataSources[j].SetGridDistanceY(100);
                        display.DataSources[j].OnRenderYAxisLabel = RenderYLabel;
                        CalcSinusFunction_0(display.DataSources[j], j);      
                        break;

                    case "NORMAL_AUTO":
                        this.Text = "Normal Graph Autoscaled";
                        display.DataSources[j].Length = 5800;
                        display.PanelLayout = PlotterGraphPaneEx.LayoutMode.NORMAL;
                        display.DataSources[j].AutoScaleY = true;
                        display.DataSources[j].SetDisplayRangeY(-300, 300);
                        display.DataSources[j].SetGridDistanceY(100);
                        display.DataSources[j].OnRenderYAxisLabel = RenderYLabel;
                        CalcSinusFunction_0(display.DataSources[j], j);
                        break;

                    case "STACKED":
                        this.Text = "Stacked Graph";
                        display.PanelLayout = PlotterGraphPaneEx.LayoutMode.STACKED;
                        display.DataSources[j].Length = 5800;
                        display.DataSources[j].AutoScaleY = false;
                        display.DataSources[j].SetDisplayRangeY(-250, 250);
                        display.DataSources[j].SetGridDistanceY(100);
                        CalcSinusFunction_1(display.DataSources[j], j);
                        break;

                    case "VERTICAL_ALIGNED":
                        this.Text = "Vertical aligned Graph";
                        display.PanelLayout = 
                            PlotterGraphPaneEx.LayoutMode.VERTICAL_ARRANGED;
                        display.DataSources[j].Length = 5800;
                        display.DataSources[j].AutoScaleY = false;
                        display.DataSources[j].SetDisplayRangeY(-300, 300);
                        display.DataSources[j].SetGridDistanceY(100);
                        CalcSinusFunction_2(display.DataSources[j], j);    
                        break;

                    case "VERTICAL_ALIGNED_AUTO":
                        this.Text = "Vertical aligned Graph autoscaled";
                        display.PanelLayout = 
                            PlotterGraphPaneEx.LayoutMode.VERTICAL_ARRANGED;
                        display.DataSources[j].Length = 5800;
                        display.DataSources[j].AutoScaleY = true;
                        display.DataSources[j].SetDisplayRangeY(-300, 300);
                        display.DataSources[j].SetGridDistanceY(100);
                        CalcSinusFunction_2(display.DataSources[j], j);
                        break;

                    case "TILED_VERTICAL":
                        this.Text = "Tiled Graphs (vertical prefered)";
                        display.PanelLayout = PlotterGraphPaneEx.LayoutMode.TILES_VER;
                        display.DataSources[j].Length = 5800;
                        display.DataSources[j].AutoScaleY = false;
                        display.DataSources[j].SetDisplayRangeY(-300, 600);
                        display.DataSources[j].SetGridDistanceY(100);
                        CalcSinusFunction_2(display.DataSources[j], j);    
                        break;

                    case "TILED_VERTICAL_AUTO":
                        this.Text = "Tiled Graphs (vertical prefered) autoscaled";
                        display.PanelLayout = PlotterGraphPaneEx.LayoutMode.TILES_VER;
                        display.DataSources[j].Length = 5800;
                        display.DataSources[j].AutoScaleY = true;
                        display.DataSources[j].SetDisplayRangeY(-300, 600);
                        display.DataSources[j].SetGridDistanceY(100);
                        CalcSinusFunction_2(display.DataSources[j], j);
                        break;

                    case "TILED_HORIZONTAL":
                        this.Text = "Tiled Graphs (horizontal prefered)";
                        display.PanelLayout = PlotterGraphPaneEx.LayoutMode.TILES_HOR;
                        display.DataSources[j].Length = 5800;
                        display.DataSources[j].AutoScaleY = false;
                        display.DataSources[j].SetDisplayRangeY(-300, 600);
                        display.DataSources[j].SetGridDistanceY(100);
                        CalcSinusFunction_2(display.DataSources[j], j);    
                        break;

                    case "TILED_HORIZONTAL_AUTO":
                        this.Text = "Tiled Graphs (horizontal prefered) autoscaled";
                        display.PanelLayout = PlotterGraphPaneEx.LayoutMode.TILES_HOR;
                        display.DataSources[j].Length = 5800;
                        display.DataSources[j].AutoScaleY = true;
                        display.DataSources[j].SetDisplayRangeY(-300, 600);
                        display.DataSources[j].SetGridDistanceY(100);
                        CalcSinusFunction_2(display.DataSources[j], j);
                        break;

                    case "ANIMATED_AUTO":
                       
                        this.Text = "Animated graphs fixed x range";
                        display.PanelLayout = PlotterGraphPaneEx.LayoutMode.TILES_HOR;
                        display.DataSources[j].Length = 402;
                        display.DataSources[j].AutoScaleY = false;
                        display.DataSources[j].AutoScaleX = true;
                        display.DataSources[j].SetDisplayRangeY(-300, 500);
                        display.DataSources[j].SetGridDistanceY(100);
                        display.DataSources[j].XAutoScaleOffset = 50;
                        CalcSinusFunction_3(display.DataSources[j], j, 0);
                        display.DataSources[j].OnRenderYAxisLabel = RenderYLabel;
                        break;
                }             
            }
            
            ApplyColorSchema();

            this.ResumeLayout();
            display.Refresh();
           
        }

函数 CalcSinusFunction_0 CalcSinusFunction_1CalcSinusFunction_2 用于计算图表中不同的正弦函数

protected void CalcSinusFunction_0(DataSource src, int idx)
{
    for (int i = 0; i  < src.Length; i++)
    {
        src.Samples[i].x = i;
        src.Samples[i].y = (float)(((float)200 * Math.Sin((idx + 1) *(
            i + 1.0) * 48 / src.Length)));
    }    
}

函数 RenderYLabelRenderXLabel 用于渲染图表的 X 和 Y 轴标签。

private String RenderXLabel(DataSource s, int idx)
{
    if (s.AutoScaleX)
    {         
        int Value = (int)(s.Samples[idx].x );
        return "" + Value;     
    }
    else
    {
        int Value = (int)(s.Samples[idx].x / 200);
        String Label = "" + Value + "\"";
        return Label;
    }    
}

private String RenderYLabel(DataSource s, float value)
{ 
    return String.Format("{0:0.0}", value);
}

摘要

这里有很多可以调整的参数,但这里没有解释 - 只要看看代码。这个库远未完成,但它是一个很好的起点。代码简单且自解释。从这里开始,很容易根据您的需要改编代码。

我从这里获得了如此多的输入,我想回馈一些东西。所以,这是我在 Code Project 上的第一篇文章。我希望你喜欢它。

待办事项

  • 代码清理。

版本历史

  • 2014 年 9 月 4 日 - 4 年来的第一次更新。重新发现了我的代码 ;-) 将解决方案升级到 VS 2013 Express。清理了一些魔数。 更多内容即将推出 ;-)
  • 2009 年 7 月 12 日 - 更新文章。
  • 2009 年 2 月 12 日 - 实现了 x 轴自动缩放。
  • 2009 年 1 月 28 日 - 更多清理。实现了打印表单。
  • 2009 年 1 月 27 日 - 新的显示模式,一些清理。
  • 2009 年 1 月 25 日 - 初始发布。
用于绘图的简单 C# 库 - CodeProject - 代码之家
© . All rights reserved.