Search code examples
rendergraphingilnumerics

ILNumeric continuous rendering plots


Is there a way to continously plot changing array data? I've got a ILLinePlot to graph the line to changing data on a button event, but I would like to make it continuous.

while (true)
{
    float[] RefArray = A.GetArrayForWrite();
    //RefArray[0] = 100;
    Shuffle<float>(ref RefArray);
    Console.Write(A.ToString());
    scene = new ILScene();
    pc = scene.Add(new ILPlotCube());
    linePlot = pc.Add(new ILLinePlot(A.T, lineColor: Color.Green));
    ilPanel1.Scene = scene;
    ilPanel1.Invalidate();

 }

The problem I'm running into is that the loop runs, and i can see updates of the array, but the ILPanel does not update. I'm thinking maybe it's because the main loop can't be accessed due to this infinite loop, so I put it in its own thread as well, but it's still not rendering as I hoped...


Solution

  • As Paul pointed out, there is a more efficient attempt to do this:

    private void ilPanel1_Load(object sender, EventArgs e) {
        using (ILScope.Enter()) {
            // create some test data
            ILArray<float> A = ILMath.tosingle(ILMath.rand(1, 50));
            // add a plot cube and a line plot (with markers)
            ilPanel1.Scene.Add(new ILPlotCube(){
                new ILLinePlot(A, markerStyle: MarkerStyle.Rectangle)
            }); 
            // register update event
            ilPanel1.BeginRenderFrame += (o, args) =>
            {
                // use a scope for automatic memory cleanup
                using (ILScope.Enter()) {
                    // fetch the existint line plot object
                    var linePlot = ilPanel1.Scene.First<ILLinePlot>(); 
                    // fetch the current positions
                    var posBuffer = linePlot.Line.Positions; 
                    ILArray<float> data = posBuffer.Storage;
                    // add a random offset 
                    data = data + ILMath.tosingle(ILMath.randn(1, posBuffer.DataCount) * 0.005f); 
                    // update the positions of the line plot
                    linePlot.Line.Positions.Update(data);
                    // fit the line plot inside the plot cube limits
                    ilPanel1.Scene.First<ILPlotCube>().Reset();
                    // inform the scene to take the update
                    linePlot.Configure();
                }
            }; 
            // start the infinite rendering loop
            ilPanel1.Clock.Running = true; 
        }
    } 
    

    Here, the full update runs inside an anonymous function, registered to BeginRenderFrame.

    The scene objects are reused instead of getting recreated in every rendering frame. At the end of the update, the scene needs to know, you are done by calling Configure on the affected node or some node among its parent nodes. This prevents the scene from rendering partial updates.

    Use an ILNumerics arteficial scope in order to clean up after every update. This is especially profitable once larger arrays are involved. I added a call to ilPanel1.Scene.First<ILPlotCube>().Reset() in order to rescale the limits of the plot cube to the new data content.

    At the end, start the rendering loop by starting the Clock of ILPanel.

    The result is a dynamic line plot, updating itself at every rendering frame.

    enter image description here