The IDrawable and IPlot Interfaces

People often email me to suggest new Plot types they think should be included in NPlot. Unfortunately, it isn't possible for me to implement all of these (due to lack of time) and some are too specific to include in a general library - I'd prefer to concentrate on providing a stable, well designed base library. The good news of course is that NPlot provides some very well defined interfaces that promote user extensibility. In this section, I'll discuss IDrawable and IPlot.

To create charts with NPlot, you add items to a "PlotSurface2D" using the Add method. This method has multiple signatures, but they all take an IDrawable as a parameter - the thing to be drawn on the plot surface.


The IDrawable interface is the simplest possible that allows drawing on a plot surface. It comprises one method:

void Draw( Graphics g, PhysicalAxis xAxis, PhysicalAxis yAxis );

The first parameter is the Graphics context - you draw to this using the standard GDI+ calls.

The last two parameters are the axes which let you determine the physical position of a world coordinate.


In NPlot, the concept of "Plot" is an object that wraps around some data, and provides functionality for drawing that data against axes of a chart. Formally, plot objects are objects that implement the IPlot interface. You can implement this interface to create new plot types allowing you to easily create custom graphical representaitions for custom data sets.

 .. the above is obviously under construction :-) ..

Some miscellaneous documentation. Applies to v0.9.9.3 and up.

Rectangle Plot

Pawel Konieczny writes: We have already a BarPlot, which allows for free value of both bar ends, but is one-dimensional. We have already a HistogramPlot, which is 2-dimensional, but the bottom is always at the abscissa axis. I needed a plot in which I could freely set the size of the bar (rectangle) depending on data values.

RectanglePlot accepts one series of (x,y) data, in which every even data point defines a left rectangle point, and every odd data point defines the diagonal right rectangle point. I use it to visualize trades, plotted on a quotes plot. This is a standard way of visualizing trades. My addition is the gradient fill, which I use to various series of trades (e.g. winning versus losing). To make the trades visualized according to their profit/loss size, the gradient can be laid on a scale: absolute, by defining the value at which gradient reaches the max color (remember the absolute scale of the image plot?) or relative, where the length of the gradient is expressed in percent change from the start.

I believe this plot will be useful to everybody working on a financial application.


Pawel Konieczny writes: VerticalMultiGuideline is my solution to have several VerticalGuidelines synchronized on horizontal mouse movement. To be more specific: imagine two plots stacked one on top of the other, for instance quotes plot above volume plot, or right audio channel plot above left audio channel plot. If I add VerticalGuideline to both plots, only one of them is visible at the time - the one in the plot over which is actually the mouse. VerticalMultiGuideline shows and synchronizes them both.

The usage is somewhat different than for the rest of interactions, because the constructor has to get the collection of NPlot.Windows.PlotSurface2D objects, on which the guidelines will be drawn. But then it still has to be added to each of those plot surfaces individually, over which the mouse move be tracked. Usually, it will be the same list, but need not be.

Example usage:

   NPlot.Windows.PlotSurface2D ps1 = new NPlot.Windows.PlotSurface2D();
   NPlot.Windows.PlotSurface2D ps2 = new NPlot.Windows.PlotSurface2D();
   /* setup both plot surfaces */
   NPlot.Windows.VerticalMultiGuideline guide =
       new NPlot.Windows.VerticalMultiGuideline(new

NPlot.Windows.PlotSurface2D[] { ps1, ps2 });



Pawel Konieczny writes: PlotRegionCursor allows for changing the cursor shape withing the plot area. Although each Windows control can have its own cursor, the plot area is not a separate control. Changing a cursor only over the plot area can be done with this interaction. I use it in the case when I have a vertical and a horizontal guide enabled for a surface. The standard cursor is then redundant, even more, it unnecessary obscures the plot surface. So I add this interaction setting the cursor to an empty (transparent) one (attached, if you want to use it in a demo program). In the future, it may be useful to make the class more rich, for instance, specifying a different cursor for the X and Y axis hover. When the AxisDrag is in use, it would be good to give a visual feedback in a form of an appropriate cursor, that the axes are draggable.