Search code examples
visual-studiovisual-c++graph

Starting point for minimal Visual C++ X-Y Graph


Is there a simple example of a program in Visual C++ that graphs x-y data?

This is to operate a small spectrometer. I would like a starting point that shows a graph and does little else, to which I will add controls, a thread that reads the data sent asynchronously from the instrument over a COM port and some plumbing to update the graph.

Thank you


Solution

  • A 'simple' plotting application is actually not all that simple. Also, if you make it as simple as possible, then adding bells and whistles is impossible without a re-write, so it becomes a dead end.

    Anyway, this is what I use for developing windows applications that need to display a plot :

    Sample plot application:
    
    #include "wex.h"          //  https://github.com/JamesBremner/windex
    #include "plot2d.h"
    
    int main()
    {
            wex::gui& fm = wex::maker::make();
            fm.move( {50,50,1200,600} );
    
            // construct plot to be drawn on form
            wex::plot::plot& thePlot = wex::maker::make<wex::plot::plot>(fm);
            thePlot.move( {30,30,1200,600});
            //thePlot.Grid( true );
    
            // resize plot when form resizes
            fm.events().resize([&](int w, int h )
            {
                thePlot.move( {30,30,w,h} );
                thePlot.update();
            });
    
            // construct plot traces
            wex::plot::trace& t1 = thePlot.AddStaticTrace();
            wex::plot::trace& t2 = thePlot.AddStaticTrace();
    
            // provide some data for first trace
            std::vector< double > d1 { 10, 15, 20, 25, 30, 25, 20, 15, 10 };
            t1.set( d1 );
    
            // plot in blue
            t1.color( 0x0000FF );
    
            // provide data for second trace
            std::vector< double > d2 { 20, 30, 40, 50, 60, 50, 40, 30, 20 };
            t2.set( d2 );
    
            // plot in red
            t2.color( 0xFF0000 );
    
            // show and run
            fm.show();
            fm.run();
    }
    

    By the way, there is no need to gather the data using a separate thread ( always a fruitful source of bugs ). Instead, use the windows API message pump, like this:

        wex::button &btnTime = wex::maker::make<wex::button>(fm);
        btnTime.move(300, 10, 100, 20);
        btnTime.text("Real Time");
        btnTime.tooltip("Display moving line plot that updates in real time");
        btnTime.events().click([&]
                               {
            // construct plot trace
            // displaying 100 points before they scroll off the plot
            plot::trace& t1 = thePlot.AddRealTimeTrace( 100 );
    
            // plot in blue
            t1.color( 0xFF0000 );
    
            // create timer handler to provide new data regularly
            fm.events().timer([&](int id)
            {
                static int p = 0;
                t1.add( 10 * sin( p++ / 10.0 ) );
                thePlot.update();
            });