• C# ScottPlot 绘图控件 源码阅读心得体会


    ScottPlot的介绍可以看这篇博客:https://www.cnblogs.com/myshowtime/p/15606399.html
    我对代码的理解是这样的:
    图像的呈现是靠bitmap,每进行拖动图像,放大缩小,等等操作,都会新创建一张图片,并把这张图片作为最新的展示在界面上。
    为了保证图片内存的回收效率,还专门创建了一个队列,这个队列会把旧图片在新图片创建时入队,当对当前图形有改变时并且当队列里的图片个数大于3时,才会出队释放图片内存。
    在【Settings】这个类里,主要是存储图像的配置和数据的,比如x y轴, 长宽 ,轴的长度限制,以及一个非常核心的观察模式的集合对象:
    ObservableCollection<IPlottable> Plottables
    图片所包括的所有显示需要渲染到图片上的对象都实现了IPlottable接口,比如坐标 刻度 插图 x轴y轴线,里面的代码如下:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    public interface IPlottable
        {
            bool IsVisible { getset; }
            void Render(PlotDimensions dims, System.Drawing.Bitmap bmp, bool lowQuality = false);
     
            int XAxisIndex { getset; }
            int YAxisIndex { getset; }
     
            /// <summary>
            /// Returns items to show in the legend. Most plottables return a single item. in this array will appear in the legend.
            /// Plottables which never appear in the legend can return null.
            /// </summary>
            LegendItem[] GetLegendItems();
     
            /// <summary>
            /// Return min and max of the horizontal and vertical data contained in this plottable.
            /// Double.NaN is used for axes not containing data.
            /// </summary>
            /// <returns></returns>
            AxisLimits GetAxisLimits();
     
            /// <summary>
            /// Throw InvalidOperationException if ciritical variables are null or have incorrect sizes.
            /// Deep validation is slower but also checks every value for NaN and Infinity.
            /// </summary>
            void ValidateData(bool deep = false);
        }
    其中核心的就是Render方法了,这个在底层调用 bmp参数的gdi,这个bmp参数就是最终显示给用户的图像。所有在 Plottables 里的对象都会渲染到这张图片上面去。【PlotDimensions】 这个对象表示该元素的长宽 位置等信息。
    暴露给用户使用的类是【Plot】类,里面有不同样式的 x y 数据类型,有单一的接受y轴数据,而x轴就平均分取。比如:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    public SignalPlot AddSignal(double[] ys, double sampleRate = 1, Color? color = nullstring label = null)
            {
                SignalPlot signal = new SignalPlot()
                {
                    Ys = ys,
                    SampleRate = sampleRate,
                    Color = color ?? settings.GetNextColor(),
                    Label = label,
     
                    // TODO: FIX THIS!!!
                    MinRenderIndex = 0,
                    MaxRenderIndex = ys.Length - 1,
                };
                Add(signal);
                return signal;
            }

     最后在返回之前 ,这个Add(signal)会把这个对象加入到Plottables 集合中去 我们还可以添加很多元素,比如:

    1
    2
    3
    4
    5
    6
    7
    8
    // plot the data
    formsPlot1.Plot.AddScatter(xs, sin);
    formsPlot1.Plot.AddScatter(xs, cos);
     
    // customize the axis labels
    formsPlot1.Plot.Title("ScottPlot Quickstart");
    formsPlot1.Plot.XLabel("Horizontal Axis");
    formsPlot1.Plot.YLabel("Vertical Axis");

     最后渲染的时候就用这个:formsPlot1.Refresh(); 它会调用Plot的 Render方法,这个方法会去遍历Plottables 这个集合,然后挨个用gdi画到bitmap上面去。 在formsPlot1控件里,有一个非常重要的类:【ControlBackEnd】,这里面有关于对图像 放大 缩小 移动 ,点击 的基本操作方法。 我们自己还可以注册这些事件写额外的代码 也不会影响。

     
    分类: 源码阅读
  • 相关阅读:
    1015
    1016
    1014
    1002
    1010
    1006
    动态规划1001
    动态规划1002
    使用EF框架调用带有输出参数(output)的存储过程
    工程地质相关知识
  • 原文地址:https://www.cnblogs.com/bruce1992/p/16639233.html
Copyright © 2020-2023  润新知