ScottPlot's introduction can be found in this blog: https://www.cnblogs.com/myshowtime/p/15606399.html
My understanding of the code is as follows:
Image presentation depends on bitmap. Every time you drag an image, zoom in and out, and so on, a new image will be created and displayed on the interface as the latest image.
In order to ensure the recovery efficiency of picture memory, a queue is specially created. This queue will queue old pictures when new pictures are created. When the current picture is changed and the number of pictures in the queue is greater than 3, the queue will release picture memory.
The [Settings] class is mainly used to store image configuration and data, such as X, Y axis, length and width, axis length limit, and a collection object of very core observation mode:
ObservableCollection<IPlottable> Plottables
All objects included in the picture that need to be rendered to the picture have implemented the IPlottable interface, such as the x-axis and y-axis of the coordinate scale illustration. The code is as follows:
public interface IPlottable { bool IsVisible { get; set; } void Render(PlotDimensions dims, System.Drawing.Bitmap bmp, bool lowQuality = false); int XAxisIndex { get; set; } int YAxisIndex { get; set; } /// <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); }
The core is the Render method, which calls the gdi of bmp parameter at the bottom, and this bmp parameter is the image finally displayed to the user. All objects in Plottables will be rendered on this picture. [PlotDimensions] this object represents the length, width, position and other information of the element.
The class exposed to the user is the [Plot] class, which has different styles of X and y data types. A single accepts y-axis data, and the x-axis is divided equally. For example:
public SignalPlot AddSignal(double[] ys, double sampleRate = 1, Color? color = null, string 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; }
Finally, before returning, the Add(signal) will add this object to the Plottables collection. We can also add many elements, such as:
// 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");
This is used for final rendering: formsPlot1.Refresh(); It will call the Render method of Plot, which will traverse the collection of Plottables, and then draw it one by one on the bitmap with gdi. In the formsPlot1 control, there is a very important class: [ControlBackEnd], which contains the basic operation methods for zooming in, zooming out, moving and clicking the image. We can also register these events ourselves and write additional code without affecting them.